Skip to main content

voxera_live_room_kit 1.0.2 copy "voxera_live_room_kit: ^1.0.2" to clipboard
voxera_live_room_kit: ^1.0.2 copied to clipboard

Real-time video live room for Flutter: host camera plus up to three guest tiles, go-live requests, host media control, chat, and minimize/PiP.

Voxera Live Room Kit #

A Flutter package for building video live-room experiences, powered by the Voxera Engine. It puts a host camera on a full-bleed stage with up to 3 invited co-publisher tiles — give it the required data and you get a fully interactive live room with no extra UI code.

The engine treats a live room as the live_stream product type: an unbounded, seatless stage. There is no seat grid and no participant cap — anyone can watch. The host invites co-publishers onto the stage (audio/video publish), while the room owner promotes moderators. The kit only caps how many guest tiles it draws (maxGuestTiles, default 3); the engine itself is uncapped.

Roles are server-authoritative. Only the verified room owner joins as the publishing host; everyone else joins as audience (watch + chat). The engine clamps any non-owner's claimed role to audience — a client cannot self-grant publish or moderation. Publishing and moderation are decoupled: being added to the stage grants publish only; being promoted to admin grants moderation only (admins are never on camera).

Features #

  • Drop-in live-room UI — host camera + up to 3 co-publisher video tiles from required data alone.
  • Stage flow — the host invites viewers onto the stage to co-publish; viewers raise-hand (stage/request) and the host adds them. No server-side queue — a request is a transient _stage_request notification to host/admins.
  • Persistent moderators — the owner can assign an identity before it joins; the engine lists online and offline admins and grants admin on the next join.
  • Host force-control — host can mute/unmute or stop a co-publisher's camera/mic, and remove them from the stage.
  • Media controls — microphone & camera with reactive state (Bluetooth-preferring audio routing).
  • Real-time chat — data-channel messages with batching and dedup.
  • Reconnection — tiered: light sync (<15s), full sync (<60s), default force-exit (>60s).
  • Minimize / PiP — minimize to a floating overlay; optional Android OS Picture-in-Picture.
  • Video effects — pairs with voxera_video_effects_kit via VoxeraLiveRoomConfig.buildVideoProcessor (a video track processor) for live filters & beauty effects.

Getting started #

Add the dependency:

dependencies:
  voxera_live_room_kit: ^1.4.0

Audio engine setup (required) #

The native media engine is built once per process, and the first thing that touches it decides its audio profile. The live kit calls this itself. If your app touches WebRTC before the first room opens, call it first in main():

import 'package:voxera_media_client/voxera_media_client.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await VoxeraMediaClient.initializeForRoom();
  runApp(const MyApp());
}

That keeps echo cancellation on. Viewers stay on a media session. Publishing a microphone uses the communication session and the loudspeaker. Do not call initialize(mediaAudioProfile: true) — that turns echo cancellation off for the rest of the process. If you ever see [VoxeraMediaClient] the media engine was already initialized in the console, something ran before this line; report it to us with the log.

Credentials — pass your appKey (no backend required) #

Ship appId + appKey (the project's publishable app key, from the Voxera console). The kit mints tokens directly from the engine with X-App-Key; the engine signs the returned per-user user_token with the project server_secret server-side, so the secret never ships in the app. The kit uses that user_token as the Authorization: Bearer for all in-room calls. No token server to stand up. appKey can't sign tokens or call the S2S API and rotates on its own.

import 'package:voxera_live_room_kit/voxera_live_room_kit.dart';

VoxeraLiveRoom(
  appId: '<voxera-app-id>',
  appKey: '<voxera-app-key>', // publishable; the kit mints tokens itself, no backend needed
  userId: 'user123',
  userName: 'Jane',
  roomId: 'room456',
  roomOwnerId: 'owner789',
  // Identities the OWNER will promote to `admin` (moderators) once they join.
  // Optional. The engine clamps non-owners to `audience`, so these are only
  // honored because the owner promotes them server-side after join.
  adminIds: const {'mod1', 'mod2'},
  config: const VoxeraLiveRoomConfig(maxGuestTiles: 3),
);

The kit defaults token and in-room requests to https://stream.zavryn.online. Override tokenBaseUrl and engineBaseUrl only for a different deployment.

Fast first join #

Warm reusable DNS/TLS, device-ID, and RTC prerequisites during app startup or before the user opens the room list. This does not mint a token, claim a session, request permissions, or turn on the camera/microphone:

await VoxeraRoomController.warmUp(
  tokenBaseUrl: 'https://stream.zavryn.online',
);

For the shortest tap-to-room path, start token generation when navigation begins and pass the same future to tokenProvider. The room still validates and adopts the server-issued user token before any RTC connection:

final controller = VoxeraRoomController()
  ..initApi(appId: appId, appKey: appKey);
final token = controller.generateToken(
  identity: userId,
  roomName: roomId,
  roomOwnerId: roomOwnerId,
  name: userName,
  role: userId == roomOwnerId ? 'host' : 'audience',
);

VoxeraLiveRoom(
  controller: controller,
  tokenProvider: () => token,
  appId: appId,
  appKey: appKey,
  userId: userId,
  userName: userName,
  roomId: roomId,
  roomOwnerId: roomOwnerId,
);

The live room is type: live_stream. The kit mints its token with type: live_stream and sends no seat parameters (seat_count, seat_mode, host_seat are ignored for a live stream — the room is uncapped). The project must have live_stream in its enabled_types in the Voxera console, otherwise POST /api/v1/token returns 403 "Type 'live_stream' is not enabled for this project". The same appId / appKey works for every product type the project has enabled — the type is a per-request field, not a separate credential.

See the exported API in lib/voxera_live_room_kit.dart — VoxeraLiveRoom, VoxeraRoomController, VoxeraStageApi, VoxeraMediaController, VoxeraChatController, and the room/role/participant models.

Stage & roles #

A live room has four server-authoritative roles:

Role Publishes Moderates How you get it
host ✅ ✅ The verified room owner (userId == roomOwnerId). Force-upgraded by the engine.
guest ✅ ❌ Host/admin invites you onto the stage.
admin ❌ ✅ The owner promotes you (moderate-only, never on camera).
audience ❌ ❌ Default for everyone non-owner — watch + chat.

Going on stage (co-publish). A viewer raises their hand (POST /api/v1/rooms/:name/stage/request), which fires a transient _stage_request data message to the host/admins (there is no persisted queue). A host/admin then adds them (.../stage/add → role becomes guest, publish granted). Removal (.../stage/remove) or self step-down (.../stage/leave) sends them back to audience. The current publisher set is GET /api/v1/rooms/:name/stage → { members: [{ identity, name, role }] }, and roster changes broadcast a _stage_update data message. These endpoints are live_stream-only (a seated room returns 400).

The kit surfaces the stage through VoxeraRoomController — inviteToSpeak, requestToSpeak, approveSpeakerRequest, rejectSpeakerRequest — and the raw endpoints via controller.stageApi (VoxeraStageApi).

Promoting a moderator. Use the owner-only persistent roster APIs; the target does not need to be in the room:

await controller.assignAdmin(targetIdentity: id, name: 'Moderator');
final admins = await controller.listAdmins(); // each row has isOnline
final offline = await controller.listAdmins(presence: 'offline');
await controller.revokeAdmin(id);

adminIds / its resolver callbacks remain as a compatibility path where the owner promotes configured identities after they join. In a stage room admin grants moderation but not publish, and the engine refuses (409) an attempt to add an admin to the stage—the capabilities stay disjoint.

maxGuestTiles is a UI-only cap. It sizes the on-screen tile strip (host + N co-publishers); the engine stage itself is unbounded. There is no seat grid — the host video is the full-bleed background and co-publishers are floating tiles above it.

Config #

VoxeraLiveRoomConfig controls the live experience. Notable fields:

  • maxGuestTiles (default 3) — how many co-publisher tiles to draw (UI cap only; the engine is uncapped).
  • autoHostCamera (default false) — publish on connect vs. self-preview → "Go Live".
  • showGoLiveButton (default true) — render the built-in "Go Live" button during host preview, or let the app drive VoxeraMediaController.goLive.
  • frontCameraOnJoin / mirrorLocalVideo / hostFit / guestFit — camera & video-fit options.
  • videoQuality (default VoxeraVideoQuality.hd, 720p) — the video publish quality for the local camera (capture resolution + publish bitrate/framerate). Tiers: low (360p ~450 kbps), sd (540p ~800 kbps), hd (720p ~1.7 Mbps), fullHd (1080p ~3 Mbps). Applied at connect; also settable headlessly via VoxeraRoomController.setVideoQuality before connect.
  • buildVideoProcessor — a video track processor factory for live filters & beauty effects (pairs with voxera_video_effects_kit).
  • Section/tile overrides — headerWidget, messagesWidget, controlsBarWidget, hostTileBuilder, guestTileBuilder, guestTileFooterBuilder, onStageTap.

Requirements #

  • A Voxera Engine token endpoint, with live_stream in the project's enabled_types.
  • Camera & microphone runtime permissions (handled via permission_handler).
0
likes
0
points
1.16k
downloads

Publisher

unverified uploader

Weekly Downloads

Real-time video live room for Flutter: host camera plus up to three guest tiles, go-live requests, host media control, chat, and minimize/PiP.

Topics

#video #live-streaming #webrtc #video-call

License

unknown (license)

Dependencies

audio_session, cached_network_image, dartz, dio, equatable, floating, flutter, flutter_bloc, flutter_screenutil, flutter_webrtc, get_it, permission_handler, pretty_dio_logger, shared_preferences, voxera_media_client

More

Packages that depend on voxera_live_room_kit