MediaSFU Flutter SDK

July 17, 2026 · View on GitHub

MediaSFU Logo

pub.dev version MIT License Flutter 3.38.1+ Dart 3.10+

MediaSFU Flutter SDK

Build video meetings, webinars, broadcasts, live streams, and collaborative rooms in Flutter without assembling the whole real-time experience from scratch.

mediasfu_sdk is the official MediaSFU Flutter WebRTC SDK. It combines ready-made room UI with headless APIs for audio, video, chat, screen sharing, whiteboards, breakout rooms, recording, real-time translation, and AI-assisted meeting workflows across Android, iOS, web, macOS, Windows, and Linux.

Quick start · Try the sandbox · Flutter guide · API reference · Self-host with MediaSFU Open

Why Product Teams Choose MediaSFU

  • Launch sooner: start with a complete meeting, webinar, broadcast, or chat interface instead of building every room interaction yourself.
  • Keep control as you grow: customize individual cards and modals, or switch to headless mode and own the entire UI without replacing the room runtime.
  • Choose your deployment: use MediaSFU Cloud for a managed backend, MediaSFU Open for self-hosting, or route room creation through your own secure proxy.
  • Build beyond basic calls: use one SDK surface for collaboration features such as polls, breakout rooms, whiteboards, recording, translation, and telephony-ready rooms.
  • Ship across Flutter targets: share the same integration model across mobile, web, and desktop while handling each platform's permissions and media requirements.

Choose The Right Starting Point

Your goalStart withWhy
Add a working room to a Flutter app quicklyMediasfuGeneric or an event-specific widgetPrebuilt participant, media, chat, and collaboration UI
Match an existing product designSDK components and MediasfuUICustomOverridesReplace selected surfaces while retaining the room runtime
Own every pixel and interactionHeadless mode with returnUI: falseReceive MediasfuParameters state and helpers in your own widgets
Run managed production infrastructureMediaSFU CloudHosted room creation, signaling, media routing, and platform services
Keep media infrastructure in your environmentMediaSFU Open with localLinkSelf-hosted deployment and infrastructure control
Work directly with mediasoup transports and producersmediasfu_mediasoup_clientLower-level client primitives without this SDK's complete product layer

Within this package, choose the integration depth that fits the product today:

Integration styleUse this whenMain APIs
Prebuilt UIYou want a complete room UI quicklyMediasfuGeneric, MediasfuConference, MediasfuWebinar, MediasfuBroadcast, MediasfuChat, ModernMediasfuGeneric
Headless runtimeYou want MediaSFU connection/media logic but your own UIreturnUI: false, updateSourceParameters, MediasfuParameters
Custom UI with SDK componentsYou want to replace selected cards, modals, or layoutscustom builders, MediasfuUICustomOverrides, exported components

For the complete implementation guide, see README_DETAILED.md. For native permissions and platform setup, see PLATFORM_SETUP.md.

Table Of Contents

Install

flutter pub add mediasfu_sdk

Minimum package requirements:

RequirementVersion
Dart>=3.10.0 <4.0.0
Flutter>=3.38.1

Use the package barrel import in application code:

import 'package:mediasfu_sdk/mediasfu_sdk.dart';

Optional features may need extra dependencies in your app:

# Android / iOS virtual backgrounds
google_mlkit_selfie_segmentation: ^0.10.0

# Web whiteboard and capture helpers
web: ^1.1.1
dart_webrtc: ^1.8.1

Backend Model

MediaSFU is not a standalone offline video widget. The Flutter package needs a MediaSFU-compatible backend for room creation, signaling, media routing, and runtime coordination.

BackendBest forWhat the Flutter app passes
MediaSFU CloudManaged production rooms with minimal infrastructureCredentials(apiUserName, apiKey)
MediaSFU Open / self-hostedOn-premise, private, or custom backend deploymentslocalLink, and optional local auth fields such as localAppKey, localApiUserName, localApiKey, localSubUserName
Your backend proxyProduction apps that should not expose privileged API keysApp-specific token/room data returned by your backend, then passed into SDK options

The built-in helper endpoints are:

HelperMediaSFU Cloud endpointSelf-hosted endpoint when localLink is not a MediaSFU domain
createRoomOnMediaSFUhttps://mediasfu.com/v1/rooms${localLink}/createRoom
joinRoomOnMediaSFUhttps://mediasfu.com/v1/rooms/${localLink}/joinRoom

Security note: avoid embedding privileged production credentials in public clients unless that is an intentional part of your architecture. A backend proxy is usually safer for production mobile and web apps.

Quick Start: Prebuilt Room

This is the fastest working path for MediaSFU Cloud. Get your API username and key from the MediaSFU developer dashboard, or use the self-hosted path instead.

import 'package:flutter/material.dart';
import 'package:mediasfu_sdk/mediasfu_sdk.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MediasfuGeneric(
        options: MediasfuGenericOptions(
          credentials: Credentials(
            apiUserName: 'your-api-username',
            apiKey: 'your-64-character-api-key',
          ),
        ),
      ),
    );
  }
}

Run it:

flutter run

The default MediasfuGeneric flow shows the pre-join page, lets the user create or join a room, then renders the meeting experience with media controls, chat, participants, recording controls, polls, whiteboard, and related modals.

Try The UI Without A Live Room

Use local UI mode when you want to test layouts, demos, screenshots, or custom components without connecting to a live room.

MediasfuGeneric(
  options: MediasfuGenericOptions(
    useLocalUIMode: true,
    useSeed: true,
    seedData: SeedData(
      member: 'Demo User',
      eventType: EventType.conference,
    ),
  ),
)

This is useful for frontend work, visual QA, and rapid prototyping. It does not replace a real backend validation pass before release.

Choose A Room Widget

Start with MediasfuGeneric or ModernMediasfuGeneric when you are still shaping the product. Move to the event-specific widgets when the room type is fixed.

WidgetUse case
MediasfuGenericGeneral room experience that can support multiple event types
ModernMediasfuGenericModern UI path with extra translation, fixed-link, and navigation options
MediasfuConferenceMeeting and team collaboration rooms
MediasfuWebinarHost, panelist, and attendee workflows
MediasfuBroadcastBroadcast and one-to-many streaming experiences
MediasfuChatChat-first rooms with optional media workflows

Example:

MediasfuConference(
  options: MediasfuConferenceOptions(
    credentials: Credentials(
      apiUserName: 'your-api-username',
      apiKey: 'your-64-character-api-key',
    ),
  ),
)

Modern UI example:

ModernMediasfuGeneric(
  options: ModernMediasfuGenericOptions(
    credentials: Credentials(
      apiUserName: 'your-api-username',
      apiKey: 'your-64-character-api-key',
    ),
    initialMeetingId: 'optional-room-id',
    onBack: () {
      // Route back with your app router.
    },
  ),
)

Headless Mode

Set returnUI: false when your app should own the visual interface while MediaSFU owns connection setup, room state, media state, and helper methods.

import 'package:flutter/material.dart';
import 'package:mediasfu_sdk/mediasfu_sdk.dart';

class HeadlessMeeting extends StatefulWidget {
  const HeadlessMeeting({super.key});

  @override
  State<HeadlessMeeting> createState() => _HeadlessMeetingState();
}

class _HeadlessMeetingState extends State<HeadlessMeeting> {
  MediasfuParameters? parameters;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        MediasfuGeneric(
          options: MediasfuGenericOptions(
            credentials: Credentials(
              apiUserName: 'your-api-username',
              apiKey: 'your-64-character-api-key',
            ),
            returnUI: false,
            updateSourceParameters: (nextParameters) {
              setState(() => parameters = nextParameters);
            },
          ),
        ),
        if (parameters == null)
          const Center(child: CircularProgressIndicator())
        else
          MyMeetingSurface(parameters: parameters!),
      ],
    );
  }
}

class MyMeetingSurface extends StatelessWidget {
  final MediasfuParameters parameters;

  const MyMeetingSurface({super.key, required this.parameters});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Room: ${parameters.roomName}'),
        Text('Participants: ${parameters.participants.length}'),
        ElevatedButton(
          onPressed: () => parameters.updateIsMessagesModalVisible(true),
          child: const Text('Open chat'),
        ),
      ],
    );
  }
}

For headless mode you usually provide one of these pre-join payloads:

MediasfuGeneric(
  options: MediasfuGenericOptions(
    returnUI: false,
    credentials: credentials,
    noUIPreJoinOptionsCreate: CreateMediaSFURoomOptions(
      action: 'create',
      duration: 60,
      capacity: 25,
      userName: 'Host User',
      eventType: EventType.conference,
    ),
    updateSourceParameters: (parameters) {
      // Store parameters in app state.
    },
  ),
)

or:

MediasfuGeneric(
  options: MediasfuGenericOptions(
    returnUI: false,
    credentials: credentials,
    noUIPreJoinOptionsJoin: JoinMediaSFURoomOptions(
      action: 'join',
      meetingID: 'room-id',
      userName: 'Guest User',
    ),
    updateSourceParameters: (parameters) {
      // Store parameters in app state.
    },
  ),
)

Create And Join Rooms Programmatically

You can call the room helpers directly when your app has its own lobby, schedule screen, or invite flow.

final createResult = await createRoomOnMediaSFU(
  CreateMediaSFUOptions(
    apiUserName: 'your-api-username',
    apiKey: 'your-64-character-api-key',
    payload: CreateMediaSFURoomOptions(
      action: 'create',
      duration: 60,
      capacity: 25,
      userName: 'Host User',
      eventType: EventType.conference,
      supportTranslation: true,
    ),
  ),
);

if (createResult.success) {
  final room = createResult.data as CreateJoinRoomResponse;
  debugPrint('Created ${room.roomName}: ${room.link}');
} else {
  final error = createResult.data as CreateJoinRoomError;
  debugPrint('Room creation failed: ${error.error}');
}

Join an existing room:

final joinResult = await joinRoomOnMediaSFU(
  JoinMediaSFUOptions(
    apiUserName: 'your-api-username',
    apiKey: 'your-64-character-api-key',
    payload: JoinMediaSFURoomOptions(
      action: 'join',
      meetingID: 'room-id',
      userName: 'Guest User',
    ),
  ),
);

if (joinResult.success) {
  final room = joinResult.data as CreateJoinRoomResponse;
  debugPrint('Joined ${room.roomName}');
}

Self-Hosted MediaSFU Open

Use localLink for self-hosted or proxy-backed deployments.

MediasfuGeneric(
  options: MediasfuGenericOptions(
    localLink: 'https://media.example.com',
    connectMediaSFU: true,
    credentials: Credentials(
      apiUserName: 'proxy-or-local-user',
      apiKey: 'your-64-character-api-key',
    ),
  ),
)

Modern self-hosted example with local socket handshake fields:

ModernMediasfuGeneric(
  options: ModernMediasfuGenericOptions(
    localLink: 'https://media.example.com',
    connectMediaSFU: true,
    credentials: credentials,
    localAppKey: 'your-app-key',
    localApiUserName: 'local-api-user',
    localApiKey: 'local-api-key',
    localSubUserName: 'team-member',
    useFixedLink: true,
    initialMeetingId: 'room-id',
  ),
)

When localLink is set to a non-MediaSFU domain, createRoomOnMediaSFU uses ${localLink}/createRoom and joinRoomOnMediaSFU uses ${localLink}/joinRoom.

Platform Setup

Most media failures are caused by missing host-app permissions. Configure each target platform before testing production flows.

PlatformRequired setup
AndroidCamera, microphone, internet permissions; min SDK and ProGuard rules as needed
iOSNSCameraUsageDescription, NSMicrophoneUsageDescription, local network permissions if applicable
macOSCamera, microphone, and network entitlements
WebHTTPS in production, browser media permissions, CORS for self-hosted servers
WindowsFlutter desktop setup and camera/microphone device permissions
LinuxFlutter desktop setup plus system media dependencies

See PLATFORM_SETUP.md for copy-ready native configuration snippets.

Common Options

These options appear across the prebuilt room widgets.

OptionTypePurpose
credentialsCredentials?MediaSFU Cloud or backend auth values
localLinkString?Self-hosted/proxy server base URL
connectMediaSFUbool?Whether the SDK should connect to MediaSFU services
returnUIbool?true renders the prebuilt UI; false runs headless
updateSourceParametersFunction(MediasfuParameters?)?Receives the runtime helper/state bundle
noUIPreJoinOptionsCreateCreateMediaSFURoomOptions?Create-room payload for headless mode
noUIPreJoinOptionsJoinJoinMediaSFURoomOptions?Join-room payload for headless mode
createMediaSFURoomCreateRoomOnMediaSFUType?Replace the create-room helper
joinMediaSFURoomJoinRoomOnMediaSFUType?Replace the join-room helper
useLocalUIModebool?Run the UI without live room connections
seedData / useSeedSeedData? / bool?Seed demo participant and room data
customVideoCardVideoCardType?Replace video cards
customAudioCardAudioCardType?Replace audio cards
customMiniCardMiniCardType?Replace mini participant cards
customComponentCustomComponentType?Replace the whole room workspace
containerStyleContainerStyleOptions?Style the room container
uiOverridesMediasfuUICustomOverrides?Wrap or replace specific SDK widgets/functions

Modern-only extras include useFixedLink, localAppKey, localApiUserName, localApiKey, localSubUserName, initialMeetingId, canUsePersonalTranslation, personalTranslationUsername, userVoiceClones, onBack, and optimizeVideoRecord.

Customization

Replace common media cards

MediasfuGeneric(
  options: MediasfuGenericOptions(
    credentials: credentials,
    customVideoCard: ({
      required participant,
      required stream,
      required width,
      required height,
      imageSize,
      doMirror,
      showControls,
      showInfo,
      name,
      backgroundColor,
      onVideoPress,
      parameters,
    }) {
      return SizedBox(
        width: width,
        height: height,
        child: DecoratedBox(
          decoration: BoxDecoration(
            color: backgroundColor ?? Colors.black,
            border: Border.all(color: Colors.blueAccent, width: 2),
            borderRadius: BorderRadius.circular(12),
          ),
          child: Center(
            child: Text(
              name ?? participant.name,
              style: const TextStyle(color: Colors.white),
            ),
          ),
        ),
      );
    },
  ),
)

The exact builder signatures are exported by the package types. Use your editor autocomplete from package:mediasfu_sdk/mediasfu_sdk.dart for the required parameters.

Wrap one SDK component with MediasfuUICustomOverrides

final overrides = MediasfuUICustomOverrides(
  participantsModal: ComponentOverride<ParticipantsModalOptions>(
    render: (context, options, defaultBuilder) {
      return Theme(
        data: Theme.of(context).copyWith(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        ),
        child: defaultBuilder(context, options),
      );
    },
  ),
);

MediasfuGeneric(
  options: MediasfuGenericOptions(
    credentials: credentials,
    uiOverrides: overrides,
  ),
)

Frequently overridden slots include mainContainer, mainGrid, controlButtons, participantsModal, messagesModal, recordingModal, pollModal, breakoutRoomsModal, configureWhiteboardModal, backgroundModal, preJoinPage, and welcomePage.

Replace the full workspace

MediasfuGeneric(
  options: MediasfuGenericOptions(
    credentials: credentials,
    customComponent: ({required parameters}) {
      return MyFullMeetingWorkspace(parameters: parameters);
    },
  ),
)

Use this when you want MediaSFU to provide the runtime state and methods while your app owns the complete room UI.

Custom icons and Font Awesome v11

The package uses font_awesome_flutter v11. When rendering Font Awesome icons directly, use FaIcon:

import 'package:font_awesome_flutter/font_awesome_flutter.dart';

const FaIcon(FontAwesomeIcons.xmark)

For SDK share button options, both Flutter IconData values and Font Awesome FaIconData values are supported:

ShareButtonOptions(
  icon: FontAwesomeIcons.whatsapp,
  action: () {},
)

Feature Map

Feature areaSDK surface
Audio/video roomsMediasfuGeneric, MediasfuConference, MediasfuParameters, media card builders
Webinars and panelistsMediasfuWebinar, panelist methods, modern panelist modal
BroadcastsMediasfuBroadcast
Chat roomsMediasfuChat, messages modal, message methods
Screen sharingscreen-share methods, screen producer helpers, screenboard components
Recordingrecording modal and recording methods
Pollspoll modal and poll methods
Breakout roomsbreakout room modal and launch methods
Whiteboardwhiteboard, screenboard, configure whiteboard modal, capture helpers
Virtual backgroundsbackground modal, processor service, platform-specific ML dependency
Waiting roomswaiting modal and waiting methods
Co-hostsco-host modal and co-host methods
Permissionspermission methods and modern permissions modal
Translationmodern translation settings, translation room config, personal translation options
SIP / telephony-ready roomsCreateMediaSFURoomOptions.supportSIP, directionSIP, preferPCMA
AI notes and agentsconfigure from the MediaSFU dashboard/docs, then use room/runtime features in the SDK

Troubleshooting

SymptomCheck
Pre-join shows credential errorsapiUserName must not be a placeholder and apiKey must be a valid 64-character key
Camera or microphone does not openNative platform permissions, HTTPS on web, and OS privacy settings
Web works locally but not in productionHTTPS, browser permission prompts, CORS for self-hosted APIs, and TURN/STUN reachability
Self-hosted create/join failsVerify localLink, /createRoom, /joinRoom, TLS, CORS, and backend auth headers
Headless mode renders no UIThis is expected with returnUI: false; render your own widgets from MediasfuParameters
Demo mode connects unexpectedlyUse useLocalUIMode: true with seed data and avoid live credentials for visual-only demos
Font Awesome compile error with Icon(FontAwesomeIcons.xmark)Use FaIcon(FontAwesomeIcons.xmark) with font_awesome_flutter v11
Analyzer reports only info-level lintsThe package may still build; clean those lints separately if your CI treats infos as fatal

Resources And Support

Use the shortest path for the question you have:

NeedLink
Flutter setup and conceptsFlutter SDK guide
Copy-and-run first integrationQuick start guide
Fully custom Flutter UIHeadless guide
Exact classes and signaturesGenerated Flutter API reference
Browse all developer materialMediaSFU docs portal
Developer console and API configurationDeveloper console guide
Dashboard user guidemediasfu.com/user-guide
Test before integratingMediaSFU sandbox
Prototype embeddable experiencesWidget Studio
Self-host the media backendMediaSFU Open
AI agentsmediasfu.com/agents
AI notesmediasfu.com/ai-notes-guide
Translationmediasfu.com/translation
SIP / telephonymediasfu.com/telephony
Community supportmediasfu.com/forums
Contactmediasfu.com/contact
GitHub organizationgithub.com/MediaSFU

For faster help, include the mediasfu_sdk version, Flutter target, chosen room widget, backend mode (MediaSFU Cloud or localLink), exact error text, and a minimal reproducible snippet. Those details also give coding assistants the context needed to suggest the correct MediaSFU APIs.

Platform/frameworkPackage or docs
Flutterpub.dev/packages/mediasfu_sdk
Reactmediasfu.com/reactjs
Angularmediasfu.com/angular
Vuemediasfu.com/vue
React Native CLImediasfu.com/reactnative
React Native Expomediasfu.com/reactnativeexpo
JavaScriptmediasfu.com/javascript

License

MIT. See LICENSE.