utd_stream_sdk 0.1.0 copy "utd_stream_sdk: ^0.1.0" to clipboard
utd_stream_sdk: ^0.1.0 copied to clipboard

Headless LiveKit-based audio/video SDK for Flutter (audio call, video call, live stream, audio room) as logic-only sessions with no UI — build your own interface.

UTD Stream SDK (headless) #

LiveKit-based audio/video for Flutter with no UI. You get the logic — sessions, state, and control methods — and build your own interface. One set of credentials (app_id + app_key) works for every product type your project enabled; the type is chosen per session, never per credential.

The four types #

Type What it is Session
audio_call 1:1 audio UTDCallSession
video_call 1:1 audio + video UTDCallSession
live_stream one host, unlimited viewers, engine-uncapped co-publishers UTDLiveStreamSession
audio_room seat-based speakers + listeners UTDAudioRoomSession

Install #

dependencies:
  utd_stream_sdk: ^0.1.0

Quick start #

final client = UTDStreamClient(appId: '1234567890', appKey: 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6');

// ── Audio room ──
final room = await client.joinAudioRoom(identity: 'u1', roomName: 'lobby', asHost: true, seatCount: 8);
await room.takeSeat(0);            // become a speaker (engine grants publish, mic turns on)
room.remoteParticipants.addListener(rebuildUI);

// ── Live stream ──
final live = await client.joinLiveStream(identity: 'host1', roomName: 'show', asHost: true);
await live.goLive();              // host publishes camera + mic
await live.inviteToStage('u2');  // invite a viewer to co-publish — no engine count limit
// viewers join as `audience` (subscribe only) and can raise a hand:
// await live.requestStage();

// ── 1:1 call ──
await client.authenticate(identity: 'u1');         // mint a bearer (calls have no room to mint first)
final call = client.callSession(UTDStreamType.videoCall);
final created = await call.start(calleeIdentity: 'u2');
// callee side: client.authenticate(identity:'u2'); await call.accept(created.callId);

live_stream: roles & the stage #

live_stream is the seatless, unbounded broadcast. There is no seat grid — seat_count / seat_mode / host_seat are ignored. The engine creates the LiveKit room uncapped (max_participants = 0) so viewers are unlimited; your app decides how many co-publisher tiles to surface (UTDLiveStreamSession.stage).

Publishing is decoupled from moderation. Four roles:

Role Publishes? Moderates? How you get it
host yes yes the verified room owner (asHost: true + roomOwnerId)
guest yes no a host-invited co-publisher (inviteToStage)
admin no yes a host-promoted moderator — never on camera
audience no no the default for everyone else

Every non-owner joins as audience. Roles are server-authoritative: the engine clamps a non-owner's claimed role to audience, so a viewer can't self-grant publish or moderation by asserting role: 'host' — promotion happens server-side only, and the SDK merely reacts to the resulting permission change (it never elevates itself).

The stage is the publisher set (host + guests). The stage REST surface moves people between audienceguest only — it never touches the admin tier:

UTDLiveStreamSession Engine endpoint Who
refreshStage() GET /api/v1/rooms/:name/stage{ members:[{identity,name,role}] } anyone
inviteToStage(id) POST /api/v1/rooms/:name/stage/add { target_identity } host/admin
removeFromStage(id) POST /api/v1/rooms/:name/stage/remove { target_identity } host/admin
leaveStage() POST /api/v1/rooms/:name/stage/leave self step-down
requestStage() POST /api/v1/rooms/:name/stage/request viewer raise-hand

The actor is resolved from the per-user bearer (the verified user), not a client-asserted body field. Adding an admin to the stage is refused (409) — moderation and publishing stay disjoint. Stage ops on a seated or non-live_stream room are 400; if live_stream isn't enabled for the project they are 403.

Moderator (admin) promotion is owner-only and not part of this SDK's stage API. It uses the engine role route PUT /api/v1/rooms/:name/participants/:identity/role { role: 'admin' } (owner-only), which grants moderation but not publish. Drive it through your moderation backend / the full kit if you need it.

Data messages the engine broadcasts on the room: _stage_update (the current roster, mirrors the stage notifier) and _stage_request (a viewer raised a hand — delivered to the host/admins). Read them off the raw events stream.

State (build any UI from these) #

Every session exposes ValueListenables — connected, canPublish, micEnabled, cameraEnabled, remoteParticipants — plus a raw events stream of LiveKit RoomEvents. Permission changes (seat/stage promote-demote) are server-authoritative: the SDK reacts to them, it never elevates itself.

Architecture #

  • UTDStreamClient — entry point; holds credentials, mints tokens, produces sessions.
  • UTDApi / UTDApiClient — engine REST (mint host uses X-App-Key; privileged host uses the server-minted Authorization: Bearer). No secret ever ships in the app.
  • UTDRoom — headless LiveKit Room wrapper (connect, publish, events).
  • session/* — one control surface per product type.

Not included (host-app responsibility) #

  • Incoming-call delivery. Receiving a ringing call (the call_id) arrives out-of-band via your push pipeline or the engine presence WebSocket; wire it, then call UTDCallSession.accept(callId).
  • UI, by design.
0
likes
0
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

Headless LiveKit-based audio/video SDK for Flutter (audio call, video call, live stream, audio room) as logic-only sessions with no UI — build your own interface.

Topics

#livekit #webrtc #voice-chat #video-call #live-streaming

License

unknown (license)

Dependencies

dio, flutter, livekit_client

More

Packages that depend on utd_stream_sdk