Sinua
Connect your appVoice

LiveKit

Show a LiveKit voice agent's state and voice as a live orb, waveform or ring in SwiftUI, Jetpack Compose and React: pass the room you already have.

Beta

The LiveKit source is beta: it is tested on simulated sessions, not yet against a live LiveKit session. If it misbehaves with your agent, an issue with the platform and version helps most.

If your app already uses LiveKit, connect the visual to the room you have. The source finds the agent participant, follows its state attribute (lk.agent.state, the same names Sinua uses), and measures the agent's audio track for the level and bands. Pass a room you've already connected, and no credential passes through Sinua. Or let the source join itself with a token from your endpoint, which answers { credential, url } (Credentials): credentialUrl on the web, iOS and React Native, LiveKitVoiceSource.withCredentialUrl(context, …) on Android. A token you already have still works: { url, token } on the web and React Native, LiveKitVoiceSource(url:token:) on iOS, LiveKitVoiceSource.owned(context, url, token) on Android.

livekit-web.ts
// npm i livekit-client (an optional peer: only apps using LiveKit install it)
import { Room } from "livekit-client";
import { LiveKitVoiceSource } from "@sinua/voice/livekit";

// Your endpoint signs a room token and answers `{ credential, url }` (see Credentials).
// The source joins the room and publishes the mic. The agent's state comes from its
// `lk.agent.state` attribute (LiveKit Agents set it).
export const voice = new LiveKitVoiceSource({ credentialUrl: "/api/voice/livekit" });

// Already have a Room (e.g. from @livekit/components-react)? Pass it; you keep ownership.
export const fromRoom = (room: Room) => new LiveKitVoiceSource({ room });

It sends transcripts of both speakers (transcriptTiming synced), synced to the played audio by default.

Packages

PlatformPackage
WebLiveKitVoiceSource from @sinua/voice/livekit (install livekit-client alongside)
iOSSinuaLiveKit (a separate Swift package, pulls client-sdk-swift)
Android:sinua-livekit (pulls livekit-android)

Good to know

  • The state comes from LiveKit Agents. Agents built with LiveKit Agents set lk.agent.state. If your agent doesn't, the source falls back to the audio: the agent is speaking while its track is loud.
  • Your room stays yours. When you pass a room, the source never disconnects it. It waits up to 20 seconds for an agent to join.
  • Say where the audio goes. Publishing the microphone sends the user's voice to your LiveKit server and the agent in the room. Your iOS purpose string (NSMicrophoneUsageDescription) and, on Android, the explanation you show before the RECORD_AUDIO prompt (the system prompt carries no app text) should say so. App Store review expects the purpose string to explain the use.
  • livekit-client is an optional peer on the web. Install it yourself, and only apps that use LiveKit pull it in.

On this page