voxa_rtc_engine 0.2.4 copy "voxa_rtc_engine: ^0.2.4" to clipboard
voxa_rtc_engine: ^0.2.4 copied to clipboard

Drop-in, Agora-API-compatible RTC SDK for Flutter on self-hosted infrastructure: same classes, signatures, error codes, and callback ordering as agora_rtc_engine 6.x, over a LiveKit-based media engine.

example/lib/main.dart

// Agora's official Flutter video-call quickstart, running on VoxaRTC.
//
// Diff vs the Agora original (the migration promise, plan §1):
//   1. the package import below           (was: package:agora_rtc_engine/...)
//   2. the two VOXA-marked config lines   (the only non-Agora addition)
// Everything else — names, signatures, callbacks, widgets — is unchanged.
import 'dart:io' show Platform;

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:voxa_rtc_engine/voxa_rtc_engine.dart'; // ← was agora_rtc_engine
import 'package:voxa_rtc_engine/voxa.dart'; // VOXA: gateway config import

// Fill in from your VoxaRTC deployment (dev defaults match infra/docker).
// Token minted 2026-08-07, wildcard uid, valid 24h — re-mint with:
//   cd voxa-compat-gateway && go run ./cmd/tokentool -channel demo -uid 0 -expire 86400
const appId = String.fromEnvironment('APP_ID',
    defaultValue: '970CA35de60c44645bbae8a215061b33');
const token = String.fromEnvironment('TOKEN', defaultValue: '');
const channel = String.fromEnvironment('CHANNEL', defaultValue: 'demo');

void main() {
  // VOXA: point the SDK at your Compat Gateway (LAN IP when using a device).
  VoxaRtc.serverUrl = const String.fromEnvironment('VOXA_SERVER',
      defaultValue: 'http://192.168.68.52:8788');
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int? _remoteUid;
  bool _localUserJoined = false;
  late RtcEngine _engine;

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

  Future<void> initAgora() async {
    // retrieve permissions
    // VOXA: guarded for the macOS dev harness — permission_handler has no
    // desktop implementation; macOS prompts natively on first device use.
    if (Platform.isAndroid || Platform.isIOS) {
      await [Permission.microphone, Permission.camera].request();
    }

    // create the engine
    _engine = createAgoraRtcEngine();
    await _engine.initialize(const RtcEngineContext(
      appId: appId,
      channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
    ));

    _engine.registerEventHandler(
      RtcEngineEventHandler(
        onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
          debugPrint('local user ${connection.localUid} joined');
          setState(() {
            _localUserJoined = true;
          });
        },
        onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
          debugPrint('remote user $remoteUid joined');
          setState(() {
            _remoteUid = remoteUid;
          });
        },
        onUserOffline: (RtcConnection connection, int remoteUid,
            UserOfflineReasonType reason) {
          debugPrint('remote user $remoteUid left channel');
          setState(() {
            _remoteUid = null;
          });
        },
        onTokenPrivilegeWillExpire: (RtcConnection connection, String token) {
          debugPrint(
              '[onTokenPrivilegeWillExpire] connection: ${connection.toJson()}, token: $token');
        },
      ),
    );

    await _engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
    await _engine.enableVideo();
    await _engine.startPreview();

    await _engine.joinChannel(
      token: token,
      channelId: channel,
      uid: 0,
      options: const ChannelMediaOptions(),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _dispose();
  }

  Future<void> _dispose() async {
    await _engine.leaveChannel();
    await _engine.release();
  }

  // Create UI with local view and remote view
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('VoxaRTC Video Call'),
        ),
        body: Stack(
          children: [
            Center(
              child: _remoteVideo(),
            ),
            Align(
              alignment: Alignment.topLeft,
              child: SizedBox(
                width: 100,
                height: 150,
                child: Center(
                  child: _localUserJoined
                      ? AgoraVideoView(
                          controller: VideoViewController(
                            rtcEngine: _engine,
                            canvas: const VideoCanvas(uid: 0),
                          ),
                        )
                      : const CircularProgressIndicator(),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  // Display remote user's video
  Widget _remoteVideo() {
    if (_remoteUid != null) {
      return AgoraVideoView(
        controller: VideoViewController.remote(
          rtcEngine: _engine,
          canvas: VideoCanvas(uid: _remoteUid),
          connection: const RtcConnection(channelId: channel),
        ),
      );
    } else {
      return const Text(
        'Please wait for remote user to join',
        textAlign: TextAlign.center,
      );
    }
  }
}
0
likes
0
points
47
downloads

Publisher

verified publisherzamansheikh.com

Weekly Downloads

Drop-in, Agora-API-compatible RTC SDK for Flutter on self-hosted infrastructure: same classes, signatures, error codes, and callback ordering as agora_rtc_engine 6.x, over a LiveKit-based media engine.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

async, flutter, http, json_annotation, livekit_client, meta

More

Packages that depend on voxa_rtc_engine

Packages that implement voxa_rtc_engine