<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nisha Goswami</title>
    <description>The latest articles on DEV Community by Nisha Goswami (@nisha_goswami_).</description>
    <link>https://dev.to/nisha_goswami_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3966252%2F7c578e92-5f3a-4922-a663-8397b44717da.png</url>
      <title>DEV Community: Nisha Goswami</title>
      <link>https://dev.to/nisha_goswami_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nisha_goswami_"/>
    <language>en</language>
    <item>
      <title>Cross-Platform Live Video App Development: Architecture, Tech Stack, Challenges, and Best Practices</title>
      <dc:creator>Nisha Goswami</dc:creator>
      <pubDate>Tue, 30 Jun 2026 13:32:02 +0000</pubDate>
      <link>https://dev.to/video-sdk/cross-platform-live-video-app-development-architecture-tech-stack-challenges-and-best-practices-29nj</link>
      <guid>https://dev.to/video-sdk/cross-platform-live-video-app-development-architecture-tech-stack-challenges-and-best-practices-29nj</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;What Is Cross-Platform Live Video App Development?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Cross-Platform Live Video App Development helps to build one real-time video experience for Android, iOS, web, and desktop without maintaining fully separate native apps.&lt;/p&gt;

&lt;p&gt;Instead of creating separate apps for iOS, Android, web, and desktop, you can use frameworks like Flutter, React Native, Kotlin Multiplatform, or .NET MAUI.&lt;/p&gt;

&lt;p&gt;The goal is to reuse code where it makes sense, reduce development time, and still provide a smooth user experience on every supported platform.&lt;/p&gt;

&lt;p&gt;A modern cross-platform live video app can include video calls, live streaming, webinars, screen sharing, chat, reactions, recording, user roles, analytics, and moderation.&lt;/p&gt;

&lt;p&gt;This guide explains the architecture, tech stack, development process, challenges, security practices, differences,  cost factors, and best practices so that you can make the best production-ready live video app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Native vs Cross-Platform Development
&lt;/h3&gt;

&lt;p&gt;Native development uses platform-specific tools like Swift for iOS and Kotlin for Android. It gives strong control over performance, device APIs, and platform behaviour.&lt;/p&gt;

&lt;p&gt;Cross-platform development allows teams to share UI, business logic, API calls, and product flows. This helps small teams ship faster and maintain features more easily.&lt;/p&gt;

&lt;p&gt;For live video, the best choice depends on product complexity, native media needs, team skills, device coverage, and the video SDK or WebRTC stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Use Cases
&lt;/h3&gt;

&lt;p&gt;Cross-platform live video apps are used in many product categories where real-time human interaction improves the user experience.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Video conferencing apps&lt;/li&gt;
&lt;li&gt;Online education platforms&lt;/li&gt;
&lt;li&gt;Telemedicine apps&lt;/li&gt;
&lt;li&gt;Fitness and coaching apps&lt;/li&gt;
&lt;li&gt;Social live streaming platforms&lt;/li&gt;
&lt;li&gt;Gaming and esports communities&lt;/li&gt;
&lt;li&gt;Creator economy apps&lt;/li&gt;
&lt;li&gt;Customer support tools&lt;/li&gt;
&lt;li&gt;Enterprise collaboration platforms&lt;/li&gt;
&lt;li&gt;Virtual events and webinars&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any business that wants users to connect live across devices can benefit from a strong cross-platform video architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the Right Cross-Platform Framework
&lt;/h2&gt;

&lt;p&gt;The framework you choose affects development speed, UI quality, native integration, SDK compatibility, performance, and long-term maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flutter
&lt;/h3&gt;

&lt;p&gt;Flutter is an open-source UI toolkit developed by Google that allows developers to build natively compiled applications for mobile, web, and desktop from a single codebase.&lt;br&gt;
Flutter is a strong choice when one want consistent UI across Android, iOS, web, and desktop. It is popular for polished product experiences.&lt;br&gt;
For live video apps, Flutter works well when the selected video SDK provides stable Flutter support and handles native media features properly.&lt;/p&gt;
&lt;h3&gt;
  
  
  React Native
&lt;/h3&gt;

&lt;p&gt;React Native is a framework for building mobile apps using JavaScript and React.&lt;br&gt;
For video apps, the main consideration is native module quality, SDK support, performance during rendering, and device permission handling.&lt;/p&gt;
&lt;h3&gt;
  
  
  Kotlin Multiplatform
&lt;/h3&gt;

&lt;p&gt;Kotlin Multiplatform allows teams to share business logic while keeping native UI on Android and iOS. This gives better native control.&lt;br&gt;
It works well for teams that want platform-specific UI quality but still want to avoid duplicating networking, models, and business logic.&lt;/p&gt;
&lt;h3&gt;
  
  
  .NET MAUI
&lt;/h3&gt;

&lt;p&gt;.NET MAUI is useful for enterprise teams working in the Microsoft ecosystem. It supports building apps for Android, iOS, macOS, and Windows.&lt;br&gt;
It may fit internal collaboration tools, enterprise communication systems, and products where C# and Microsoft infrastructure are already common.&lt;/p&gt;
&lt;h3&gt;
  
  
  Framework Comparison Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Strengths&lt;/th&gt;
&lt;th&gt;Considerations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flutter&lt;/td&gt;
&lt;td&gt;Consumer apps, startups, polished UI&lt;/td&gt;
&lt;td&gt;Consistent UI, fast iteration, strong design control&lt;/td&gt;
&lt;td&gt;Needs stable video SDK support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Native&lt;/td&gt;
&lt;td&gt;JavaScript teams, fast product development&lt;/td&gt;
&lt;td&gt;Large ecosystem, easier hiring, reusable components&lt;/td&gt;
&lt;td&gt;Native modules can add complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kotlin Multiplatform&lt;/td&gt;
&lt;td&gt;Native-first mobile apps&lt;/td&gt;
&lt;td&gt;Shared logic with native UI&lt;/td&gt;
&lt;td&gt;Smaller ecosystem than React Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET MAUI&lt;/td&gt;
&lt;td&gt;Enterprise apps&lt;/td&gt;
&lt;td&gt;C# support, Microsoft ecosystem&lt;/td&gt;
&lt;td&gt;Not ideal for every consumer product&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The right choice depends on the product goal, performance needs, platform coverage, development timeline, and the video SDK or media stack being used.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Technology Stack for Cross-Platform Live Video Apps
&lt;/h2&gt;

&lt;p&gt;A live video app needs multiple layers working together. These layers include frontend, backend, signaling, media servers, cloud infrastructure, databases, and observability.&lt;/p&gt;
&lt;h3&gt;
  
  
  Frontend Layer
&lt;/h3&gt;

&lt;p&gt;The frontend handles camera access, microphone access, video rendering, speaker controls, participant list, chat, reactions, screen sharing, and room navigation.&lt;/p&gt;

&lt;p&gt;Common frontend choices include Flutter, React Native, web apps using React or Vue, and native modules where deeper platform control is needed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Backend Layer
&lt;/h3&gt;

&lt;p&gt;The backend manages users, authentication, room creation, permissions, session records, payment logic, webhooks, notifications, and admin workflows.&lt;/p&gt;

&lt;p&gt;Common backend technologies include Node.js, Go, Java, .NET, and Python. The best choice depends on your team's skill and scaling needs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Real-Time Communication Layer
&lt;/h3&gt;

&lt;p&gt;For interactive video calls, WebRTC is commonly used because it supports real-time audio, video, and data communication between clients.&lt;/p&gt;

&lt;p&gt;For broadcast-style streaming, RTMP can be used for ingest, while HLS is commonly used for large-scale playback with higher latency.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Latency Profile&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WebRTC&lt;/td&gt;
&lt;td&gt;Video calls, classrooms, telehealth, gaming&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;td&gt;Best for interactive sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTMP&lt;/td&gt;
&lt;td&gt;Stream ingest, creator broadcasting&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Often used before transcoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLS&lt;/td&gt;
&lt;td&gt;Large-scale playback and recorded video&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Reliable for one-to-many viewing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SRT&lt;/td&gt;
&lt;td&gt;Reliable contribution streaming&lt;/td&gt;
&lt;td&gt;Low to medium&lt;/td&gt;
&lt;td&gt;Useful for unstable networks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Media Server Layer
&lt;/h3&gt;

&lt;p&gt;Media servers route, forward, mix, or process audio and video streams. They are critical when moving beyond small peer-to-peer calls.&lt;/p&gt;

&lt;p&gt;Common media server options include SFU-based systems, Janus, mediasoup, Jitsi, LiveKit, or managed videoSDK infrastructure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Cloud Infrastructure
&lt;/h3&gt;

&lt;p&gt;Cloud infrastructure provides compute, networking, storage, global regions, deployment automation, monitoring, and scaling capacity.&lt;/p&gt;

&lt;p&gt;AWS, Google Cloud, and Azure are common choices. For live video, region selection matters because physical distance affects latency.&lt;/p&gt;

&lt;p&gt;For broadcast and recorded playback, CDN planning is important. A CDN helps deliver video content to viewers across regions with less buffering.&lt;/p&gt;
&lt;h3&gt;
  
  
  Database and Cache
&lt;/h3&gt;

&lt;p&gt;PostgreSQL can store structured user, room, and billing data. MongoDB can store flexible session metadata. Redis works well for presence and caching.&lt;/p&gt;

&lt;p&gt;Most production apps use more than one storage technology because session state, recordings, analytics, and user data have different needs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Live Video App Architecture Explained
&lt;/h2&gt;

&lt;p&gt;A production-grade cross-platform live video app usually includes client apps, authentication, signaling, media routing, storage, CDN, analytics, and monitoring.&lt;/p&gt;
&lt;h3&gt;
  
  
  Client Layer
&lt;/h3&gt;

&lt;p&gt;The client layer includes mobile apps, web apps, and desktop apps. It handles capture, rendering, controls, permissions, and user interactions.&lt;/p&gt;

&lt;p&gt;The client should gracefully handle weak networks, permission denial, camera switching, background mode, reconnection, and audio output changes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Authentication Service
&lt;/h3&gt;

&lt;p&gt;The authentication service verifies user identity and issues secure tokens. It decides who can join, publish, subscribe, record, or moderate.&lt;/p&gt;

&lt;p&gt;Tokens should be short-lived and role-based. A viewer should not have the same access as a host or moderator.&lt;/p&gt;
&lt;h3&gt;
  
  
  Signaling Server
&lt;/h3&gt;

&lt;p&gt;The signaling server helps clients exchange information required to establish a media connection. It manages room state, participant events, and connection metadata.&lt;/p&gt;

&lt;p&gt;Signaling does not usually carry actual audio or video. It helps clients and media servers connect correctly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Media Server
&lt;/h3&gt;

&lt;p&gt;The media server receives audio and video streams and forwards them to other participants. In group calls, an SFU is commonly used.&lt;/p&gt;

&lt;p&gt;This reduces bandwidth and CPU pressure compared to full mesh peer-to-peer calls where every participant sends streams to every other participant.&lt;/p&gt;
&lt;h3&gt;
  
  
  Storage and CDN
&lt;/h3&gt;

&lt;p&gt;Storage is used for recordings, thumbnails, chat history, logs, and compliance data. CDN integration improves playback for recorded videos and large broadcasts.&lt;/p&gt;

&lt;p&gt;CDNs are more useful for one-to-many streaming and recorded playback than for fully interactive video calls.&lt;/p&gt;
&lt;h3&gt;
  
  
  Monitoring and Analytics
&lt;/h3&gt;

&lt;p&gt;Monitoring tracks packet loss, jitter, latency, bitrate, dropped frames, join failure, crashes, and server health.&lt;/p&gt;

&lt;p&gt;A live video platform without monitoring is difficult to improve because users may report quality issues without clear technical evidence.&lt;br&gt;
This approach helps developers avoid building WebRTC signaling, room management, participant events, and media handling from scratch. VideoSDK already provides SDKs for platforms like Flutter, React Native, JavaScript, Android, and iOS.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Build a Cross-Platform Live Video App Using VideoSDK
&lt;/h2&gt;

&lt;p&gt;The easiest way to build a cross-platform live video app is to use VideoSDK’s implementation flow: create a developer account, generate an auth token, create a room, join the room from your app, render participants, and add meeting controls.&lt;/p&gt;

&lt;p&gt;This approach helps developers avoid building WebRTC signaling, room management, participant events, and media handling from scratch. VideoSDK already provides SDKs for platforms like Flutter, React Native, JavaScript, Android, and iOS.&lt;/p&gt;

&lt;p&gt;If you are still exploring the best approach or want to understand how the implementation works, this &lt;a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt; is a good place to start. It helps you test the flow quickly and see how everything connects in practice.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/4h57eVcaC34"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Development Challenges and Solutions
&lt;/h2&gt;

&lt;p&gt;Live video apps face different challenges from normal mobile or web apps. The app must handle real-time media, unpredictable networks, and device differences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Instability
&lt;/h3&gt;

&lt;p&gt;Users may join from mobile data, weak Wi-Fi, office networks, shared hostels, or public hotspots. Network quality can change during the session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use adaptive bitrate, reconnection, network indicators, audio-only fallback, and graceful UI messages when quality drops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low Latency Requirements
&lt;/h3&gt;

&lt;p&gt;Interactive video needs low delay. High latency makes conversations awkward and can break use cases like support, teaching, gaming, and healthcare.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use WebRTC for real-time sessions, nearby media servers, efficient signaling, and avoid unnecessary transcoding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalability
&lt;/h3&gt;

&lt;p&gt;A two-person call is simple compared to a virtual event with thousands of viewers or a classroom platform with many parallel sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use SFU architecture, distributed media servers, autoscaling, load balancing, and CDN playback for large broadcast audiences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Device Compatibility
&lt;/h3&gt;

&lt;p&gt;Different devices handle camera permissions, microphone routing, Bluetooth devices, codecs, background mode, and screen sharing differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Test on real devices, track device-specific failures, and choose SDKs with proven cross-platform support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Battery Consumption
&lt;/h3&gt;

&lt;p&gt;Live video uses camera, microphone, CPU, GPU, and network continuously. Poor optimization can drain mobile battery quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use hardware acceleration, efficient codecs, background handling, lower resolution when needed, and avoid unnecessary local rendering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Audio and Video Sync
&lt;/h3&gt;

&lt;p&gt;Audio-video sync issues make sessions feel unprofessional. They can happen because of buffering, jitter, processing delay, or device performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use stable media pipelines, monitor jitter, avoid unnecessary media processing, and test across devices and network conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bandwidth Optimization
&lt;/h3&gt;

&lt;p&gt;Group video calls can consume high bandwidth. This creates cost issues for the business and quality issues for users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use simulcast, adaptive bitrate, selective subscriptions, audio-only fallback, and sensible default video quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Factors in Cross-Platform Live Video Development
&lt;/h2&gt;

&lt;p&gt;The cost of building a cross-platform live video app depends less on the framework and more on how the app handles real-time media, scale, storage, and reliability.&lt;/p&gt;

&lt;p&gt;A simple one-to-one video calling MVP can be built faster with a managed video SDK. But a large live streaming platform with recording, moderation, analytics, multi-region support, and compliance needs a bigger budget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Cost Drivers
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost Factor&lt;/th&gt;
&lt;th&gt;What It Includes&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;App Complexity&lt;/td&gt;
&lt;td&gt;Video calls, live streaming, chat, screen sharing, recording, reactions, and moderation&lt;/td&gt;
&lt;td&gt;More features increase development, testing, and maintenance effort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platform Coverage&lt;/td&gt;
&lt;td&gt;Android, iOS, web, desktop, tablets, and different browser versions&lt;/td&gt;
&lt;td&gt;More platforms mean more compatibility testing and edge cases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video Usage&lt;/td&gt;
&lt;td&gt;Number of participants, session duration, video quality, and active rooms&lt;/td&gt;
&lt;td&gt;Live video consumes bandwidth continuously, so usage directly affects cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure&lt;/td&gt;
&lt;td&gt;Media servers, TURN servers, SFU, CDN, storage, monitoring, and scaling&lt;/td&gt;
&lt;td&gt;Real-time video needs infrastructure built for low latency and reliability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recording and Playback&lt;/td&gt;
&lt;td&gt;Cloud recording, file storage, thumbnails, transcripts, and playback delivery&lt;/td&gt;
&lt;td&gt;Storage and CDN costs grow as recorded content increases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security and Compliance&lt;/td&gt;
&lt;td&gt;Token access, encryption, audit logs, data retention, GDPR, HIPAA, or SOC 2 needs&lt;/td&gt;
&lt;td&gt;Regulated apps need stronger controls and more engineering review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Bug fixes, SDK updates, device testing, analytics, monitoring, and support&lt;/td&gt;
&lt;td&gt;Live video apps need ongoing optimization after launch&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Startup vs Enterprise Cost Difference
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;Startup MVP&lt;/th&gt;
&lt;th&gt;Enterprise-Grade App&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main Goal&lt;/td&gt;
&lt;td&gt;Launch quickly and validate the idea&lt;/td&gt;
&lt;td&gt;Build for reliability, scale, and compliance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best Approach&lt;/td&gt;
&lt;td&gt;Use a video SDK and managed infrastructure&lt;/td&gt;
&lt;td&gt;Use SDK or custom architecture with strict controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature Set&lt;/td&gt;
&lt;td&gt;Calling, basic chat, recording, simple roles&lt;/td&gt;
&lt;td&gt;Advanced roles, analytics, compliance, moderation, multi-region support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing Needs&lt;/td&gt;
&lt;td&gt;Core device and browser testing&lt;/td&gt;
&lt;td&gt;Wider device, network, security, and load testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost Risk&lt;/td&gt;
&lt;td&gt;Bandwidth and product changes&lt;/td&gt;
&lt;td&gt;Compliance, uptime, security, and scale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For most developers, students, builders, and startups, the smarter approach is to avoid building the complete video infrastructure from scratch. A video SDK reduces backend complexity and helps you focus on the product experience.&lt;/p&gt;

&lt;p&gt;For CTOs and larger teams, the cost discussion should include long-term reliability, observability, compliance, scaling, support, and vendor flexibility. The cheapest option at the beginning is not always the most cost-effective option at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build vs Buy: Should You Use a Video SDK?
&lt;/h2&gt;

&lt;p&gt;One of the biggest decisions in Cross-Platform Live Video App Development is whether to build media infrastructure or use a video SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Build From Scratch
&lt;/h3&gt;

&lt;p&gt;Building from scratch may make sense if video infrastructure is your core product differentiator and your team has strong WebRTC and media engineering experience.&lt;/p&gt;

&lt;p&gt;You should also have budget for signaling, SFU, TURN, recording, observability, scaling, security, SDK maintenance, and long-term infrastructure support.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use a Video SDK
&lt;/h3&gt;

&lt;p&gt;Using a video SDK is better when your team wants to launch faster, reduce infrastructure work, and focus on product experience.&lt;/p&gt;

&lt;p&gt;A good SDK provides cross-platform support, real-time communication APIs, recording, screen sharing, analytics, webhooks, security controls, and global infrastructure.&lt;/p&gt;

&lt;p&gt;For VideoSDK.live users, this approach helps developers add video calls, live streaming, chat, recording, and interactive features without building the media layer alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Video SDK Evaluation Checklist
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;What to Check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Platform Support&lt;/td&gt;
&lt;td&gt;Flutter, React Native, web, Android, iOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Latency&lt;/td&gt;
&lt;td&gt;Real-time performance for target regions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Features&lt;/td&gt;
&lt;td&gt;Calls, streaming, recording, chat, screen share&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Group calls, webinars, large sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Tokens, roles, encryption, compliance support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;Quickstarts, examples, API clarity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;Call quality, logs, webhooks, debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;Bandwidth, recording, participant minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;SLA, response time, migration help&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The best SDK is not the one with the longest feature list. It is the one that matches your product, team, budget, and scaling plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Cross-Platform Live Video App Development is a practical approach for teams that want to deliver real-time communication across Android, iOS, web, and desktop.&lt;/p&gt;

&lt;p&gt;The success of a live video app depends on more than choosing Flutter or React Native. Teams need the right media architecture, security model, scaling plan, and monitoring.&lt;/p&gt;

&lt;p&gt;For most startups and product teams, using a reliable video SDK is the fastest way to launch without owning the full complexity of WebRTC infrastructure.&lt;/p&gt;

&lt;p&gt;For enterprises, the focus should be reliability, compliance, access control, analytics, and long-term scalability across regions and devices.&lt;/p&gt;

&lt;p&gt;If your team is planning a live video product, start with the use case, define the required features, choose the right stack, and design for real-world network conditions.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. What is cross-platform live video app development?
&lt;/h3&gt;

&lt;p&gt;Cross-platform live video app development means building real-time video applications that work across Android, iOS, web, and desktop using shared code or reusable logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Is Flutter good for live video apps?
&lt;/h3&gt;

&lt;p&gt;Yes, Flutter can work well for live video apps when the selected video SDK has stable Flutter support and handles native media performance properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Is React Native good for video calling apps?
&lt;/h3&gt;

&lt;p&gt;React Native is a good choice for teams using JavaScript or TypeScript. The key is choosing reliable native modules or a strong video SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Which protocol is best for low-latency video?
&lt;/h3&gt;

&lt;p&gt;WebRTC is usually best for interactive low-latency video calls. HLS is better for large-scale playback where a few seconds of delay is acceptable.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. How is WebRTC different from RTMP and HLS?
&lt;/h3&gt;

&lt;p&gt;WebRTC is designed for real-time communication. RTMP is often used for stream ingest, while HLS is commonly used for scalable video playback.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. What are the biggest challenges in live video app development?
&lt;/h3&gt;

&lt;p&gt;The biggest challenges include network instability, latency, device compatibility, scalability, bandwidth cost, security, recording, and monitoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. How can developers reduce video latency?
&lt;/h3&gt;

&lt;p&gt;Developers can reduce latency by using WebRTC, nearby media servers, efficient signaling, adaptive bitrate, and avoiding unnecessary media processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Should startups build video infrastructure from scratch?
&lt;/h3&gt;

&lt;p&gt;Most startups should use a videoSDK because it reduces development time, infrastructure complexity, and maintenance cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. How much does it cost to build a cross-platform live video app?
&lt;/h3&gt;

&lt;p&gt;The cost depends on features, platforms, team size, video infrastructure, bandwidth, recording, security, and compliance requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Which industries benefit most from live video apps?
&lt;/h3&gt;

&lt;p&gt;Healthcare, education, fitness, gaming, social media, customer support, events, creator platforms, and enterprise collaboration benefit strongly from live video.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Choose a Real-Time Communication API for a WebRTC App</title>
      <dc:creator>Nisha Goswami</dc:creator>
      <pubDate>Fri, 26 Jun 2026 13:40:45 +0000</pubDate>
      <link>https://dev.to/nisha_goswami_/how-to-choose-a-real-time-communication-api-for-a-webrtc-app-2edp</link>
      <guid>https://dev.to/nisha_goswami_/how-to-choose-a-real-time-communication-api-for-a-webrtc-app-2edp</guid>
      <description>

&lt;p&gt;If you are building a WebRTC app, you are not just choosing a video SDK, You are choosing the infrastructure that will affect call quality, latency, recording, transcription, live streaming, mobile support, developer speed, and long-term scaling.&lt;/p&gt;

&lt;p&gt;Most teams evaluate platforms like &lt;strong&gt;VideoSDK, Agora, Twilio, and LiveKit&lt;/strong&gt; when building real-time video or audio features. However, the right choice depends on what your product needs beyond a basic video call.&lt;/p&gt;

&lt;p&gt;Here are the key factors that help in choosing the right real-time communication API for a WebRTC app:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Cross-platform SDK support
&lt;/h2&gt;

&lt;p&gt;A good RTC API should work across the platforms your users already use.&lt;br&gt;
For most WebRTC products, that means support for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;React Native&lt;/li&gt;
&lt;li&gt;Android&lt;/li&gt;
&lt;li&gt;iOS&lt;/li&gt;
&lt;li&gt;Flutter&lt;/li&gt;
&lt;li&gt;Backend or REST APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one area where VideoSDK is useful because it provides SDKs across web, mobile, and backend environments. If your product roadmap includes web today and mobile later, choosing an API with strong cross-platform support helps avoid rebuilding the communication layer again.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Managed infrastructure instead of WebRTC complexity
&lt;/h2&gt;

&lt;p&gt;WebRTC is powerful, but production WebRTC is not simple.&lt;br&gt;
You need to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Media routing&lt;/li&gt;
&lt;li&gt;SFU architecture&lt;/li&gt;
&lt;li&gt;Participant events&lt;/li&gt;
&lt;li&gt;Network changes&lt;/li&gt;
&lt;li&gt;Device permissions&lt;/li&gt;
&lt;li&gt;Browser behavior&lt;/li&gt;
&lt;li&gt;Call quality&lt;/li&gt;
&lt;li&gt;Recording&lt;/li&gt;
&lt;li&gt;Scaling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A managed RTC API like VideoSDK helps teams focus on the product experience instead of operating the full media infrastructure themselves. This is especially useful if your team wants to build custom video calls, in-app voice, customer support video chat, live streaming, or video collaboration without spending months on infrastructure.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Built-in production features
&lt;/h2&gt;

&lt;p&gt;A basic video SDK may help you start a call. A production-ready RTC API should support the full workflow around that call.&lt;br&gt;
Look for features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Group video calls&lt;/li&gt;
&lt;li&gt;Screen sharing&lt;/li&gt;
&lt;li&gt;Recording&lt;/li&gt;
&lt;li&gt;Transcription&lt;/li&gt;
&lt;li&gt;HLS streaming&lt;/li&gt;
&lt;li&gt;RTMP streaming&lt;/li&gt;
&lt;li&gt;End-to-end encryption&lt;/li&gt;
&lt;li&gt;Participant controls&lt;/li&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;li&gt;Monitoring and debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VideoSDK fits well here because it is not limited to simple audio/video calling. It also supports recording, transcription, HLS, RTMP, E2EE, SIP Connect, and real-time communication workflows that developers usually need after the first version of the app is live.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Developer experience and quickstart quality
&lt;/h2&gt;

&lt;p&gt;The best real-time communication API for live video apps should be easy to test quickly.&lt;br&gt;
Before choosing any platform, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How easily you can create a room&lt;/li&gt;
&lt;li&gt;How quickly you can join a meeting&lt;/li&gt;
&lt;li&gt;Whether mic and camera controls are straightforward&lt;/li&gt;
&lt;li&gt;How participants are rendered&lt;/li&gt;
&lt;li&gt;The clarity of documentation&lt;/li&gt;
&lt;li&gt;Availability of working examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VideoSDK’s &lt;a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noopener noreferrer"&gt;React quickstart&lt;/a&gt; is useful because it follows a simple flow that makes it easy for developers to move from evaluation to implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Pricing and scaling clarity
&lt;/h2&gt;

&lt;p&gt;When evaluating pricing for real-time video APIs, it is important to look beyond the base video minute cost.&lt;br&gt;
A real WebRTC app may also involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recording usage&lt;/li&gt;
&lt;li&gt;Transcription&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Streaming (HLS or RTMP)&lt;/li&gt;
&lt;li&gt;TURN usage&lt;/li&gt;
&lt;li&gt;Analytics&lt;/li&gt;
&lt;li&gt;Mobile SDK support&lt;/li&gt;
&lt;li&gt;Enterprise-level features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The right API is not always the cheapest one on paper. It is the one that provides predictable costs aligned with your actual product usage and growth.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing a WebRTC call with the VideoSDK React Quickstart
&lt;/h2&gt;

&lt;p&gt;Once you know what to look for in a real-time communication API, the next step is to test how fast you can actually build with it.&lt;/p&gt;
&lt;h2&gt;
  
  
  App Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgw0fje4usf0mhfl6pi8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgw0fje4usf0mhfl6pi8z.png" alt="Real time communications API react" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before proceeding, ensure that your development environment meets the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VideoSDK Developer Account (If you don’t have one, create it from the &lt;a href="https://app.videosdk.live/login" rel="noopener noreferrer"&gt;VideoSDK Dashboard&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Basic understanding of React&lt;/li&gt;
&lt;li&gt;Familiarity with &lt;a href="https://www.npmjs.com/package/@videosdk.live/react-sdk" rel="noopener noreferrer"&gt;React VideoSDK&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Node.js and NPM installed on your device&lt;/li&gt;
&lt;li&gt;Basic understanding of React Hooks (&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useRef&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;React Context API (optional)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Token Generation
&lt;/h2&gt;

&lt;p&gt;Token is used to create and validate a meeting using API and also initialise a meeting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; One should have a VideoSDK account to generate a token. Visit the VideoSDK &lt;a href="https://app.videosdk.live/login" rel="noopener noreferrer"&gt;dashboard&lt;/a&gt; to generate your token.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;VideoSDK’s React quickstart follows a simple flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a React app&lt;/li&gt;
&lt;li&gt;Install the VideoSDK React SDK&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;API.js&lt;/code&gt; file for room creation&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;MeetingProvider&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a join screen&lt;/li&gt;
&lt;li&gt;Add meeting controls&lt;/li&gt;
&lt;li&gt;Render participants&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s walk through the same quickstart flow.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Create a React app
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; npx create-react-app videosdk-rtc-react-app
&lt;span class="nb"&gt;cd &lt;/span&gt;videosdk-rtc-react-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 2: Install VideoSDK
&lt;/h2&gt;

&lt;p&gt;Install the VideoSDK React package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"@videosdk.live/react-sdk"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For participant video rendering, also install &lt;code&gt;react-player&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"react-player"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your basic project structure will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root
├── node_modules
├── public
├── src
│   ├── API.js
│   ├── App.js
│   ├── index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Create API.js
&lt;/h2&gt;

&lt;p&gt;Create a file named &lt;code&gt;API.js&lt;/code&gt; inside the &lt;code&gt;src&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;This file will handle the API call for creating a new VideoSDK room.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// API.js&lt;/span&gt;

&lt;span class="c1"&gt;//This is the Auth token, you will use it to generate a meeting and connect to it&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;Generated-from-dashbaord&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// API call to create a meeting&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createMeeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.videosdk.live/v2/rooms`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;//Destructuring the roomId from the response&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For production, do not expose the auth token directly in the frontend. Generate the token from your backend or use a backend endpoint to create rooms securely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: Wire App.js with VideoSDK components
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;App.js&lt;/code&gt;, import the VideoSDK React SDK components and hooks.&lt;/p&gt;

&lt;p&gt;You will use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MeetingProvider&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useMeeting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useParticipant&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VideoPlayer&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;MeetingProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;MeetingConsumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useMeeting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useParticipant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;VideoPlayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@videosdk.live/react-sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createMeeting&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./API&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;JoinScreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;getMeetingAndToken&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ParticipantView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MeetingView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMeetingId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Getting the meeting id by calling the api we just wrote&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getMeetingAndToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meetingId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createMeeting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setMeetingId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;//This will set Meeting Id to null when meeting is left or ended&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMeetingLeave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setMeetingId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;meetingId&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MeetingProvider&lt;/span&gt;
      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;micEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;webcamEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C.V. Raman&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MeetingView&lt;/span&gt; &lt;span class="na"&gt;meetingId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onMeetingLeave&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMeetingLeave&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MeetingProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;JoinScreen&lt;/span&gt; &lt;span class="na"&gt;getMeetingAndToken&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getMeetingAndToken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;MeetingProvider&lt;/code&gt; gives the child components access to meeting state, participant data, and meeting controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Create the JoinScreen component
&lt;/h2&gt;

&lt;p&gt;The join screen lets a user create a new meeting or join an existing meeting ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;JoinScreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;getMeetingAndToken&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMeetingId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getMeetingAndToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter Meeting Id"&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setMeetingId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Join&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; or &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Create Meeting&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbvfg4yf9fdfc8djwy2j6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbvfg4yf9fdfc8djwy2j6.jpeg" alt="joinScreen Component" width="720" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the input is empty, a new meeting is created. If a meeting ID is entered, the user joins that meeting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Create MeetingView and Controls
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;MeetingView&lt;/code&gt; handles the meeting state. It lets the user join the meeting and renders the participants once the meeting is joined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MeetingView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;joined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setJoined&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;//Get the method which will be used to join the meeting.&lt;/span&gt;
  &lt;span class="c1"&gt;//We will also get the participants list to display all participants&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;participants&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMeeting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;//callback for when meeting is joined successfully&lt;/span&gt;
    &lt;span class="na"&gt;onMeetingJoined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setJoined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JOINED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;//callback for when meeting is left&lt;/span&gt;
    &lt;span class="na"&gt;onMeetingLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onMeetingLeave&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;joinMeeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setJoined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JOINING&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Meeting Id: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meetingId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;joined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;joined&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JOINED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Controls&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          //For rendering all the participants in the meeting
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;participants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;participantId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ParticipantView&lt;/span&gt;
              &lt;span class="na"&gt;participantId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;participantId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;participantId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;joined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;joined&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JOINING&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Joining the meeting...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;joinMeeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Join&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add the meeting controls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;leave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleMic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleWebcam&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMeeting&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;leave&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Leave&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toggleMic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;toggleMic&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toggleWebcam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;toggleWebcam&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output of Controls Component&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftxymzml7l4zpb047uzow.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftxymzml7l4zpb047uzow.jpeg" alt="WebRTC controls component" width="720" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this, the user can join, leave, mute/unmute the mic, and turn the webcam on/off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Implement Participant View
&lt;/h2&gt;

&lt;p&gt;Before implementing the participant view, you need to understand a couple of concepts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Forwarding Ref for mic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The useRef hook is responsible for referencing the audio component. It will be used to play and stop the audio of the participant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;micRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;useParticipant Hook&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The useParticipant hook is responsible for handling all the properties and events of one particular participant joined in the meeting. It will take participantId as argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;micStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;webcamOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;micOn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useParticipant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;participantId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;MediaStream API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The MediaStream API is beneficial for adding a MediaTrack to the audio tag, enabling the playback of audio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;micRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MediaStream&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;mediaStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTrack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;micStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;micElem.current.play() failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Only use the MediaStream API for microphone access. The VideoPlayer component in VideoSDK automatically handles the video stream.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you can use both of the hooks and the API to create ParticipantView.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ParticipantView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;micRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;micStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;webcamOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;micOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;useParticipant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;participantId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;micOn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;micStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MediaStream&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;mediaStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTrack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;micStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mediaStream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;videoElem.current.play() failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;micStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;micOn&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Participant: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; | Webcam: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;webcamOn&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ON&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OFF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; | Mic:&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;micOn&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ON&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OFF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;audio&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;micRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;autoPlay&lt;/span&gt; &lt;span class="na"&gt;playsInline&lt;/span&gt; &lt;span class="na"&gt;muted&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLocal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;webcamOn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;VideoPlayer&lt;/span&gt;
          &lt;span class="na"&gt;participantId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;participantId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Required&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"video"&lt;/span&gt;
          &lt;span class="na"&gt;containerStyle&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;300px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;300px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-full"&lt;/span&gt;
          &lt;span class="na"&gt;classNameVideo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-full"&lt;/span&gt;
          &lt;span class="na"&gt;videoStyle&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8: Run the project
&lt;/h2&gt;

&lt;p&gt;Start the React app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a meeting&lt;/li&gt;
&lt;li&gt;Join a meeting using a meeting ID&lt;/li&gt;
&lt;li&gt;Toggle mic&lt;/li&gt;
&lt;li&gt;Toggle webcam&lt;/li&gt;
&lt;li&gt;Leave the meeting&lt;/li&gt;
&lt;li&gt;Render participants in the call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives developers a practical way to evaluate VideoSDK before building a full production WebRTC app.&lt;br&gt;
You can checkout the complete &lt;a href="https://github.com/videosdk-live/quickstart/tree/main/react-rtc" rel="noopener noreferrer"&gt;quick start example here.&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
