mediasfu_sdk 2.1.8 copy "mediasfu_sdk: ^2.1.8" to clipboard
mediasfu_sdk: ^2.1.8 copied to clipboard

MediaSFU SDK for Flutter provides powerful streaming capabilities for creating high-performance cross-platform applications.

example/lib/main.dart

// ignore_for_file: unused_import, unused_shown_name, dead_code
import 'package:flutter/material.dart';
import 'package:mediasfu_sdk/mediasfu_sdk.dart';

void main() {
  runApp(const MyApp());
}

/// A custom pre-join page widget that can be used instead of the default Mediasfu pre-join page.
///
/// This widget displays a personalized welcome message and includes a button to proceed to the session.
///
/// **Note:** Ensure this widget is passed to [MediasfuGenericOptions] only when you intend to use a custom pre-join page.
Widget myCustomPreJoinPage({
  PreJoinPageOptions? options,
  required Credentials credentials,
}) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Welcome to MediaSFU'),
    ),
    body: Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            'Hello, ${credentials.apiUserName}!',
            style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 20),
          const Text(
            'Get ready to join your session.',
            style: TextStyle(fontSize: 18),
          ),
          const SizedBox(height: 40),
          ElevatedButton(
            onPressed: () {
              // Proceed to the session by updating the validation status
              if (options != null) {
                options.parameters.updateValidated(true);
              }
            },
            child: const Text('Join Now'),
          ),
        ],
      ),
    ),
  );
}

/// The main application widget for MediaSFU.
///
/// This widget initializes the necessary credentials and configuration for the MediaSFU application,
/// including options for using seed data to generate random participants and messages.
/// It allows selecting different event types such as broadcast, chat, webinar, and conference.
///
class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  // ignore: library_private_types_in_public_api
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // Provides access to the source parameters if not using the default UI (returnUI = false in options). See more in the guide.
  final ValueNotifier<MediasfuParameters?> sourceParameters =
      ValueNotifier(null);

  // Update function to update source parameters if not using the default UI (returnUI = false in options). See more in the guide.
  void updateSourceParameters(MediasfuParameters? parameters) {
    sourceParameters.value = parameters;
    // _onSourceParametersChanged(parameters);
  }

  // =========================================================
  //   CUSTOM USAGE OF SOURCE PARAMETERS FOR NON-DEFAULT UI
  // =========================================================

  // trigger click video after 5 seconds; this is just an example, best usage is building a custom UI
  // to handle these functionalities with buttons clicks, etc.
  //
  void triggerClickVideo() {
    Future.delayed(const Duration(seconds: 5), () {
      sourceParameters.value
          ?.clickVideo(ClickVideoOptions(parameters: sourceParameters.value!));
    });
  }

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

    // Attach the listener
    sourceParameters.addListener(() {
      _onSourceParametersChanged(sourceParameters.value);
    });

    // trigger click video after 5 seconds, uncomment to trigger
    // triggerClickVideo();
  }

  @override
  void dispose() {
    // Detach the listener; irrelevant if not 'returnUI = false'
    // Comment out if not using sourceParameters
    sourceParameters.removeListener(() {
      _onSourceParametersChanged(sourceParameters.value);
    });
    sourceParameters.dispose();
    super.dispose();
  }

  // ==============================================================
  //  SOURCE PARAMETERS LISTENER (REQUIRED ONLY IF USING CUSTOM UI)
  // ==============================================================

  /// Listener for changes in sourceParameters.
  /// Prints the updated parameters to the console whenever they change.
  void _onSourceParametersChanged(MediasfuParameters? parameters) {
    if (parameters != null) {
      // if (kDebugMode) {
      //   print('Source Parameters Updated: ${parameters.roomName}');
      // }
      // Add custom logic here
    }
  }

  @override
  Widget build(BuildContext context) {
    // =========================================================
    //                API CREDENTIALS CONFIGURATION
    // =========================================================

    /**
     * Scenario A: Not using MediaSFU Cloud at all.
     * - Dummy credentials are needed to render PreJoinPage. 
     * Example:
     */
    /*
    final credentials = Credentials(
      apiUserName: 'dummyUsr',
      apiKey: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
    );
    final localLink = 'http://your-ce-server.com'; // e.g., http://localhost:3000
    final connectMediaSFU = false; // Set to false if not using MediaSFU Cloud
    */

    /**
     * Scenario B: Using MediaSFU CE + MediaSFU Cloud for Egress only.
     * - Use dummy credentials (8 chars for userName, 64 chars for apiKey).
     * - Your CE backend will forward requests with your real credentials.
     */
    /*
    final credentials = Credentials(
      apiUserName: 'dummyUsr',
      apiKey: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
    );
    final localLink = 'http://your-ce-server.com'; // e.g., http://localhost:3000
    final connectMediaSFU = true; // Set to true if using MediaSFU Cloud for egress
    */

    /**
     * Scenario C: Using MediaSFU Cloud without your own server.
     * - For development, use your actual or dummy credentials.
     * - In production, securely handle credentials server-side and use custom room functions.
     */
    final credentials = Credentials(
      apiUserName: 'yourDevUser', // 8 chars recommended for dummy
      apiKey:
          'yourDevApiKey1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', // 64 chars
    );
    const localLink = ''; // Leave empty if not using your own server
    const connectMediaSFU =
        true; // Set to true if using MediaSFU Cloud since localLink is empty

    // =========================================================
    //                    UI RENDERING OPTIONS
    // =========================================================

    /**
     * If you want a fully custom UI (e.g., a custom layout inspired by WhatsApp):
     * 1. Set `returnUI = false` to prevent the default MediaSFU UI from rendering.
     * 2. Provide `noUIPreJoinOptions` to simulate what would have been entered on a pre-join page.
     * 3. Use `sourceParameters` and `updateSourceParameters` to access and update state/actions.
     * 4. No need for any of the above if you're using the default MediaSFU UI.
     */

    // Example noUIPreJoinOptions for creating a room
    final CreateMediaSFURoomOptions noUIPreJoinOptionsCreate =
        CreateMediaSFURoomOptions(
      action: 'create',
      capacity: 10,
      duration: 15,
      eventType: EventType.broadcast,
      userName: 'Prince',
    );

    // Example noUIPreJoinOptions for joining a room
    /*
    final JoinMediaSFURoomOptions noUIPreJoinOptionsJoin = JoinMediaSFURoomOptions(
      action: 'join',
      userName: 'Prince',
      meetingID: 'yourMeetingID',
    );
    */

    const bool returnUI =
        true; // Set to false for custom UI, true for default MediaSFU UI

    // State management using ValueNotifier (can be replaced with other state management solutions)
    final ValueNotifier<MediasfuParameters?> sourceParameters =
        ValueNotifier(null);

    // void updateSourceParameters(MediasfuParameters? data) {
    //   sourceParameters.value = data;
    // }

    // =========================================================
    //                CUSTOM ROOM FUNCTIONS (OPTIONAL)
    // =========================================================

    /**
     * To securely forward requests to MediaSFU:
     * - Implement custom `createMediaSFURoom` and `joinMediaSFURoom` functions.
     * - These functions send requests to your server, which then communicates with MediaSFU Cloud.
     *
     * Already implemented `createRoomOnMediaSFU` and `joinRoomOnMediaSFU` are examples.
     *
     * If using MediaSFU CE backend, ensure your server endpoints:
     * - Validate dummy credentials.
     * - Forward requests to mediasfu.com with real credentials.
     */

    // =========================================================
    //              CHOOSE A USE CASE / COMPONENT
    // =========================================================

    /**
     * Multiple components are available depending on your event type:
     * MediasfuBroadcast, MediasfuChat, MediasfuWebinar, MediasfuConference
     *
     * By default, we'll use MediasfuGeneric with custom settings.
     */

    // =========================================================
    //                    RENDER COMPONENT
    // =========================================================

    /**
     * The MediasfuGeneric component is used by default.
     * You can replace it with any other component based on your event type.
     * Example: MediasfuBroadcast(options: ...)
     * Example: MediasfuChat(options: ...)
     * Example: MediasfuWebinar(options: ...)
     * Example: MediasfuConference(options: ...)
     *
     * The PreJoinPage component is displayed if `returnUI` is true.
     * If `returnUI` is false, `noUIPreJoinOptions` is used as a substitute.
     * You can also use `sourceParameters` to interact with MediaSFU functionalities directly.
     * Avoid using `useLocalUIMode` or `useSeed` in new implementations.
     * Ensure that real credentials are not exposed in the frontend.
     * Use HTTPS and secure backend endpoints for production.
     */

    // Example configurations (uncomment as needed)

    /*
    // Example of MediaSFU CE with no MediaSFU Cloud
    final options = MediasfuGenericOptions(
      preJoinPageWidget: PreJoinPage(),
      localLink: localLink,
    );
    */

    /*
    // Example of MediaSFU CE + MediaSFU Cloud for Egress only
    final options = MediasfuGenericOptions(
      preJoinPageWidget: PreJoinPage(),
      credentials: credentials,
      localLink: localLink,
      connectMediaSFU: connectMediaSFU,
    );
    */

    /*
    // Example of MediaSFU Cloud only
    final options = MediasfuGenericOptions(
      preJoinPageWidget: PreJoinPage(),
      credentials: credentials,
      connectMediaSFU: connectMediaSFU,
    );
    */

    /*
    // Example of MediaSFU CE + MediaSFU Cloud for Egress only with custom UI
    final options = MediasfuGenericOptions(
      preJoinPageWidget: PreJoinPage(),
      credentials: credentials,
      localLink: localLink,
      connectMediaSFU: connectMediaSFU,
      returnUI: false,
      noUIPreJoinOptions: noUIPreJoinOptionsCreate,
      sourceParameters: sourceParameters.value,
      updateSourceParameters: updateSourceParameters,
      createMediaSFURoom: createRoomOnMediaSFU,
      joinMediaSFURoom: joinRoomOnMediaSFU,
    );
    */

    /*
    // Example of MediaSFU Cloud only with custom UI
    final options = MediasfuGenericOptions(
      preJoinPageWidget: PreJoinPage(),
      credentials: credentials,
      connectMediaSFU: connectMediaSFU,
      returnUI: false,
      noUIPreJoinOptions: noUIPreJoinOptionsCreate,
      sourceParameters: sourceParameters.value,
      updateSourceParameters: updateSourceParameters,
      createMediaSFURoom: createRoomOnMediaSFU,
      joinMediaSFURoom: joinRoomOnMediaSFU,
    );
    */

    /*
    // Example of using MediaSFU CE only with custom UI
    final options = MediasfuGenericOptions(
      preJoinPageWidget: PreJoinPage(),
      localLink: localLink,
      connectMediaSFU: false,
      returnUI: false,
      noUIPreJoinOptions: noUIPreJoinOptionsCreate,
      sourceParameters: sourceParameters.value,
      updateSourceParameters: updateSourceParameters,
    );
    */

    // === Main Activated Example ===
    // Default to MediasfuGeneric with credentials and custom UI options
    final MediasfuGenericOptions options = MediasfuGenericOptions(
      // Uncomment the following lines to use a custom pre-join page
      /*
      preJoinPageWidget: ({PreJoinPageOptions? options}) {
        return myCustomPreJoinPage(
          credentials: credentials,
        );
      },
      */

      // Uncomment the following lines to enable local UI mode with seed data
      /*
      useLocalUIMode: true,
      useSeed: true,
      seedData: seedData,
      */

      // Pass your Credentials if you will be using MediaSFU Cloud for recording and other egress processes or as your primary server
      credentials: credentials,

      // Use your own MediaSFU server link if you are using MediaSFU Community Edition
      // Pass your credentials if you will be using MediaSFU Cloud for recording and other egress processes or as your primary server
      connectMediaSFU: connectMediaSFU,

      // Uncomment the following line to specify your own MediaSFU Community Edition server
      localLink: localLink, // e.g., 'http://localhost:3000'

      // Set to false to use a custom UI, true to use the default MediaSFU UI
      returnUI: returnUI,

      // Provide pre-join options if not using the default UI (if creating a room)
      noUIPreJoinOptionsCreate:
          !returnUI ? noUIPreJoinOptionsCreate : null, // if creating a room

      // Provide pre-join options if not using the default UI (if joining a room)
      // noUIPreJoinOptionsJoin: !returnUI ? noUIPreJoinOptionsJoin : null, // if joining a room

      // Manage source parameters if not using the default UI
      sourceParameters: !returnUI ? sourceParameters.value : null,

      // Update source parameters if not using the default UI
      updateSourceParameters: !returnUI ? updateSourceParameters : null,

      // Provide custom room functions if not using the default functions
      createMediaSFURoom: createRoomOnMediaSFU,
      joinMediaSFURoom: joinRoomOnMediaSFU,
    );

    return MaterialApp(
      title: 'MediaSFU Generic',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuGeneric(options: options),
    );

    // === Alternative Use Cases ===
    // Uncomment the desired block to use a different MediaSFU component

    /*
    // Simple Use Case (Welcome Page)
    // Renders the default welcome page
    // No additional inputs required
    return MaterialApp(
      title: 'MediaSFU Welcome',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuGeneric(),
    );
    */

    /*
    // Use Case with Pre-Join Page (Credentials Required)
    // Uses a pre-join page that requires users to enter credentials
    return MaterialApp(
      title: 'MediaSFU Pre-Join',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuGeneric(
        options: MediasfuGenericOptions(
          preJoinPageWidget: PreJoinPage(),
          credentials: credentials,
        ),
      ),
    );
    */

    /*
    // Use Case with Local UI Mode (Seed Data Required)
    // Runs the application in local UI mode using seed data
    return MaterialApp(
      title: 'MediaSFU Local UI',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuGeneric(
        options: MediasfuGenericOptions(
          useLocalUIMode: true,
          useSeed: true,
          seedData: seedData!,
        ),
      ),
    );
    */

    /*
    // MediasfuBroadcast Component
    // Uncomment to use the broadcast event type
    return MaterialApp(
      title: 'MediaSFU Broadcast',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuBroadcast(
        credentials: credentials,
        useLocalUIMode: useLocalUIMode,
        useSeed: useSeed,
        seedData: useSeed ? seedData! : SeedData(),
      ),
    );
    */

    /*
    // MediasfuChat Component
    // Uncomment to use the chat event type
    return MaterialApp(
      title: 'MediaSFU Chat',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuChat(
        credentials: credentials,
        useLocalUIMode: useLocalUIMode,
        useSeed: useSeed,
        seedData: useSeed ? seedData! : SeedData(),
      ),
    );
    */

    /*
    // MediasfuWebinar Component
    // Uncomment to use the webinar event type
    return MaterialApp(
      title: 'MediaSFU Webinar',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuWebinar(
        credentials: credentials,
        useLocalUIMode: useLocalUIMode,
        useSeed: useSeed,
        seedData: useSeed ? seedData! : SeedData(),
      ),
    );
    */

    /*
    // MediasfuConference Component
    // Uncomment to use the conference event type
    return MaterialApp(
      title: 'MediaSFU Conference',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediasfuConference(
        credentials: credentials,
        useLocalUIMode: useLocalUIMode,
        useSeed: useSeed,
        seedData: useSeed ? seedData! : SeedData(),
      ),
    );
    */
  }
}

/**
 * =======================
 * ====== EXTRA NOTES ======
 * =======================
 *
 * ### Handling Core Methods
 * With `sourceParameters`, you can access core methods such as `clickVideo` and `clickAudio`:
 *
 * ```dart
 * // Example of toggling video
 * void toggleVideo(SourceParameters sourceParameters) {
 *   sourceParameters.clickVideo({...sourceParameters});
 * }
 *
 * // Example of toggling audio
 * void toggleAudio(SourceParameters sourceParameters) {
 *   sourceParameters.clickAudio({...sourceParameters});
 * }
 * ```
 *
 * This allows your custom UI to interact with MediaSFU's functionalities seamlessly.
 *
 * ### Seed Data (Deprecated)
 * The seed data functionality is deprecated and maintained only for legacy purposes.
 * It is recommended to avoid using it in new implementations.
 *
 * ### Security Considerations
 * - **Protect API Credentials:** Ensure that API credentials are not exposed in the frontend. Use environment variables and secure backend services to handle sensitive information.
 * - **Use HTTPS:** Always use HTTPS to secure data transmission between the client and server.
 * - **Validate Inputs:** Implement proper validation and error handling on both client and server sides to prevent malicious inputs.
 *
 * ### Custom Backend Example for MediaSFU CE
 * Below is an example of how to set up custom backend endpoints for creating and joining rooms using MediaSFU CE. Assume all unlisted imports are exported by the package:
 *
 * ```typescript
 * import express from 'express';
 * import fetch from 'node-fetch';
 * 
 * const app = express();
 * app.use(express.json());
 * 
 * app.post("/createRoom", async (req, res) => {
 *   try {
 *     const { apiUserName, apiKey } = req.headers.authorization.replace("Bearer ", "").split(":");
 *     if (!apiUserName || !apiKey || !verifyCredentials(apiUserName, apiKey)) {
 *       return res.status(401).json({ error: "Invalid credentials" });
 *     }
 * 
 *     const response = await fetch("https://mediasfu.com/v1/rooms/", {
 *       method: "POST",
 *       headers: {
 *         "Content-Type": "application/json",
 *         Authorization: `Bearer ${apiUserName}:${apiKey}`,
 *       },
 *       body: JSON.stringify(req.body),
 *     });
 * 
 *     const result = await response.json();
 *     res.status(response.status).json(result);
 *   } catch (error) {
 *     res.status(500).json({ error: "Internal server error" });
 *   }
 * });
 * 
 * app.post("/joinRoom", async (req, res) => {
 *   try {
 *     const { apiUserName, apiKey } = req.headers.authorization.replace("Bearer ", "").split(":");
 *     if (!apiUserName || !apiKey || !verifyCredentials(apiUserName, apiKey)) {
 *       return res.status(401).json({ error: "Invalid credentials" });
 *     }
 * 
 *     const response = await fetch("https://mediasfu.com/v1/rooms/join", {
 *       method: "POST",
 *       headers: {
 *         "Content-Type": "application/json",
 *         Authorization: `Bearer ${apiUserName}:${apiKey}`,
 *       },
 *       body: JSON.stringify(req.body),
 *     });
 * 
 *     const result = await response.json();
 *     res.status(response.status).json(result);
 *   } catch (error) {
 *     res.status(500).json({ error: "Internal server error" });
 *   }
 * });
 * ```
 *
 * ### Custom Room Function Implementation
 * Below are examples of how to implement custom functions for creating and joining rooms securely in Dart. Assume all unlisted imports are exported by the package:
 *
 * ```dart
 * Future<CreateJoinRoomResult> createRoomOnMediaSFU(
 *   CreateMediaSFURoomOptions options,
 * ) async {
 *   try {
 *     final payload = options.payload;
 *     final apiUserName = options.apiUserName;
 *     final apiKey = options.apiKey;
 *     String endpoint = 'https://mediasfu.com/v1/rooms/';
 * 
 *     if (options.localLink.isNotEmpty) {
 *       endpoint = '${options.localLink}/createRoom';
 *     }
 * 
 *     final response = await http.post(
 *       Uri.parse(endpoint),
 *       headers: {
 *         "Content-Type": "application/json",
 *         "Authorization": "Bearer $apiUserName:$apiKey",
 *       },
 *       body: jsonEncode(payload.toMap()),
 *     );
 * 
 *     if (response.statusCode == 200 || response.statusCode == 201) {
 *       final data = jsonDecode(response.body);
 *       return CreateJoinRoomResult(
 *         data: CreateJoinRoomResponse.fromJson(data),
 *         success: true,
 *       );
 *     } else {
 *       final error = jsonDecode(response.body);
 *       return CreateJoinRoomResult(
 *         data: CreateJoinRoomError.fromJson(error),
 *         success: false,
 *       );
 *     }
 *   } catch (_) {
 *     return CreateJoinRoomResult(
 *       data: CreateJoinRoomError(error: 'Unknown error'),
 *       success: false,
 *     );
 *   }
 * }
 * 
 * Future<CreateJoinRoomResult> joinRoomOnMediaSFU(
 *   JoinMediaSFURoomOptions options,
 * ) async {
 *   try {
 *     final payload = options.payload;
 *     final apiUserName = options.apiUserName;
 *     final apiKey = options.apiKey;
 *     String endpoint = 'https://mediasfu.com/v1/rooms/join';
 * 
 *     if (options.localLink.isNotEmpty) {
 *       endpoint = '${options.localLink}/joinRoom';
 *     }
 * 
 *     final response = await http.post(
 *       Uri.parse(endpoint),
 *       headers: {
 *         "Content-Type": "application/json",
 *         "Authorization": "Bearer $apiUserName:$apiKey",
 *       },
 *       body: jsonEncode(payload.toMap()),
 *     );
 * 
 *     if (response.statusCode == 200 || response.statusCode == 201) {
 *       final data = jsonDecode(response.body);
 *       return CreateJoinRoomResult(
 *         data: CreateJoinRoomResponse.fromJson(data),
 *         success: true,
 *       );
 *     } else {
 *       final error = jsonDecode(response.body);
 *       return CreateJoinRoomResult(
 *         data: CreateJoinRoomError.fromJson(error),
 *         success: false,
 *       );
 *     }
 *   } catch (_) {
 *     return CreateJoinRoomResult(
 *       data: CreateJoinRoomError(error: 'Unknown error'),
 *       success: false,
 *     );
 *   }
 * }
 * ```
 *
 * #### Assumptions:
 * - All unlisted imports such as `http`, `CreateMediaSFURoomOptions`, `JoinMediaSFURoomOptions`, `CreateJoinRoomResult`, `CreateJoinRoomResponse`, and `CreateJoinRoomError` are exported by the package.
 * - This structure ensures type safety, clear error handling, and flexibility for customization.
 *
 * ========================
 * ====== END OF GUIDE ======
 * ========================
 */
4
likes
125
points
124
downloads

Publisher

verified publishermediasfu.com

Weekly Downloads

MediaSFU SDK for Flutter provides powerful streaming capabilities for creating high-performance cross-platform applications.

Homepage
Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

audioplayers, clipboard, collection, flutter, flutter_colorpicker, flutter_webrtc, font_awesome_flutter, http, intl, mediasfu_mediasoup_client, shared_preferences, socket_io_client, url_launcher

More

Packages that depend on mediasfu_sdk