voxa_rtc_engine
A drop-in, Agora-API-compatible RTC engine for Flutter — on infrastructure you own.
VoxaRTC replicates the public API of agora_rtc_engine
(compat line 6.x, pinned to 6.6.3). Same classes, same method
signatures, same enums, same error codes, same callback ordering — so an
existing Agora Flutter app migrates without rewriting business logic.
Full documentation: voxa.zamansheikh.com/docs/
⚠️ Early release. The Tier-1/Tier-2 surface listed below is implemented and behaviour-verified against recordings from the live Agora service, and is carrying real traffic. Anything outside it fails gracefully rather than silently. Test your own call flows before you switch a production app over.
Migration from Agora
1. Swap the dependency:
dependencies:
voxa_rtc_engine: ^0.3.0 # was: agora_rtc_engine: ^6.6.3
2. Swap the import (find & replace):
// before
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
// after
import 'package:voxa_rtc_engine/voxa_rtc_engine.dart';
3. Point the SDK at your VoxaRTC endpoint — the only new line:
import 'package:voxa_rtc_engine/voxa.dart';
void main() {
VoxaRtc.serverUrl = 'https://gate.example.com';
runApp(const MyApp());
}
Everything else stays: createAgoraRtcEngine(), RtcEngine,
joinChannel(), RtcEngineEventHandler, AgoraVideoView, and your
existing tokens — both Agora token formats are verified (legacy 006
and 007 AccessToken2), so most token servers migrate by pointing at new
credentials, or by importing the ones they already sign with and changing
nothing at all.
Android permissions
The package's Android module declares the RTC permissions (CAMERA,
RECORD_AUDIO, MODIFY_AUDIO_SETTINGS, INTERNET,
ACCESS_NETWORK_STATE, Bluetooth), so they merge into your app exactly as
agora_rtc_engine does — no manifest edit needed when migrating. Your app
still requests them at runtime as before (e.g. with permission_handler).
On iOS/macOS, add the usual usage descriptions to Info.plist
(NSCameraUsageDescription, NSMicrophoneUsageDescription) — same as with
Agora.
Known dependency conflict: wakelock_plus
Apps that use wakelock_plus (common in live-streaming apps) will hit a
version-solve failure: the media engine pulls device_info_plus 12.x,
which pins win32 5.x, while wakelock_plus needs win32 6.x. Lift
device_info_plus — 13.x uses win32 6.x and satisfies both:
dependency_overrides:
device_info_plus: ^13.2.0
Do not pin win32 directly: Dart type-checks a package's Windows sources
even in an Android-only build, so forcing it produces analysis errors in
files that never run.
Quick example
final engine = createAgoraRtcEngine();
await engine.initialize(const RtcEngineContext(
appId: '<your VoxaRTC app id>',
channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
));
engine.registerEventHandler(RtcEngineEventHandler(
onJoinChannelSuccess: (connection, elapsed) => print('joined'),
onUserJoined: (connection, remoteUid, elapsed) => print('peer $remoteUid'),
));
await engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
await engine.enableVideo();
await engine.startPreview();
await engine.joinChannel(
token: token, channelId: 'demo', uid: 0,
options: const ChannelMediaOptions(),
);
// Rendering — unchanged from Agora:
AgoraVideoView(
controller: VideoViewController(
rtcEngine: engine,
canvas: const VideoCanvas(uid: 0),
),
);
What's implemented
Channel & lifecycle — initialize, release, joinChannel,
leaveChannel, renewToken, connection-state machine, auto-reconnect
(onRejoinChannelSuccess), token lifecycle
(onTokenPrivilegeWillExpire, onRequestToken).
Media — enable/disable audio & video, local/remote mute (incl.
muteAllRemote*), roles (broadcaster/audience) via setClientRole or
updateChannelMediaOptions, switchCamera, speakerphone routing, pre-join
startPreview, setVideoEncoderConfiguration, dual-stream/simulcast
(enableDualStreamMode, setRemoteVideoStreamType), screen share,
volume indication, in-call stats (onRtcStats, onNetworkQuality).
In-room music — startAudioMixing and family. The file is mixed into
the outgoing microphone stream natively, so remote participants hear it as
part of your audio, exactly as with Agora. Playout and publish volumes,
duration, position, seek, looping, and the state callbacks. (Pitch,
playback speed and dual-mono are not implemented.)
Behavioural compatibility — callback order, error codes, and idempotency quirks (double-join, mute-before-join, uid 0 auto-assign…) are verified against recordings from the real Agora service via a golden-transcript test harness, not just written from documentation.
Not supported at this stage (calls return
AgoraRtcException(-4, errNotSupported) instead of crashing): media
player, spatial audio, channel media relay, raw frame observers, RTM.
| Platform | Status |
|---|---|
| Android | ✅ tested on devices |
| macOS | ✅ tested |
| iOS | 🟡 expected to work (same media engine + audio mixing code as macOS), not yet device-verified |
| Web | ❌ not yet |
What you need on the server
This SDK connects to a VoxaRTC endpoint, which verifies your Agora-format tokens and issues the media session. Use a managed one, or run it yourself — setup, tokens and the full integration guide are at voxa.zamansheikh.com/docs/.
License
MIT © Zaman Sheikh (VoxaRTC). Portions of the API-surface declarations
are derived from agora_rtc_engine (MIT) — see THIRD_PARTY_LICENSES.
"Agora" is a trademark of Agora, Inc.; this project is an independent,
API-compatible implementation and is not affiliated with or endorsed by
Agora, Inc.
Libraries
- voxa
- VoxaRTC-specific configuration.
- voxa_rtc_engine
- VoxaRTC — Agora-API-compatible RTC engine for Flutter.