Every type the SDK exports, in one place — for autocomplete and type-safe config.
Importing types
Import any type directly from the package. Use import type for type-only imports.
tsx
import type { AvatarConfig, AvatarMode, AvatarSpeech, AvatarVoiceSettings, AvatarEventMap, UseAvatarResult, LiveContextArgs,} from "@avatarfactory/react-native";// Runtime valuesimport { AvatarRuntimeState, AvatarErrorCode } from "@avatarfactory/react-native";
The types match the web SDK exactly, so code that works with config or speech data can be shared between your web and mobile projects.
AvatarMode
The four operational modes. Passed as mode in AvatarConfig.
tsx
type AvatarMode = "player" | "tts" | "audio" | "call";
AvatarConfig
The configuration object for <AvatarProvider>. For production authenticate with getSessionToken; apiKey (test keys only, af_test_*) is for local development.
tsx
type AvatarConfig = AvatarConfigBase & { getSessionToken?: () => Promise<string>; apiKey?: string; // test keys only (af_test_*); dev only};type AvatarConfigBase = { // Session wiring mode?: AvatarMode; turnTaking?: TurnTakingConfig; controls?: { enabled: boolean; stopSpeaking?: boolean }; perception?: { camera?: boolean }; transcript?: TranscriptConfig; statusBanner?: StatusBannerConfig; connectTone?: ConnectToneConfig; // `src` is ignored on React Native debug?: boolean; // Agent definition avatar: { avatarId: string; layout?: Record<string, string>; // platform-agnostic layout pairs systemPrompt?: string; // identity & instructions (call mode) brain?: AvatarBrain; voiceSettings?: AvatarVoiceSettings; languages?: AvatarLanguages; greeting?: GreetingConfig; };};type AvatarBrain = { provider: "openai" | "anthropic" | "groq" | (string & {}); model?: string; useOwnBrain?: boolean; // bill the model to your own vendor key};type TurnTakingConfig = { mode?: "auto" | "push-to-talk"; // default "auto" // `spacebar` exists on the type but has no meaning on mobile.};type GreetingConfig = { enabled: boolean; message?: string; // omit for the built-in line language?: "en" | "es" | "fr" | "de" | "hi" | "ru" | "pt" | "ja" | "it";};type AvatarLanguages = | "auto" | Array<"en" | "es" | "fr" | "de" | "hi" | "ru" | "pt" | "ja" | "it" | "nl">;
React Native ships no thinking indicator, so there is no
thinkingIndicator config — read useAvatar().isResponseSlow and render your
own. connectTone.src is accepted but ignored; mobile always uses the
built-in tone.
On mobile, use getSessionToken for production — never ship a live key, since app bundles can be inspected. The apiKey method is for local development only and accepts test keys (af_test_*); live keys are rejected.
AvatarVoiceSettings
Per-session voice tuning. All fields are optional. visimeMs sets the viseme grouping window — visemes within this many milliseconds are merged into one mouth shape; the rest are passed to the voice engine — see your voice provider's docs for valid ranges.
tsx
type TtsProvider = "elevenlabs" | "inworld";type AvatarVoiceSettings = { provider?: TtsProvider; // which speech engine voices the avatar voiceId?: string; // a specific voice on that provider useOwnVoice?: boolean; // route speech through your own account visimeMs?: number; // viseme grouping window (ms); default 40 voiceSpeed?: number; // passed to the voice engine voiceStability?: number; // passed to the voice engine similarityBoost?: number; // passed to the voice engine};
type AvatarSpeech = { audioChunks: string[]; // base64-encoded audio segments alignments: NormalizedAlignment[]; // per-character timing for lip-sync isGreeting?: boolean; // mark as a greeting clip};
NormalizedAlignment
Character-level timing data that drives the lip-sync animation engine.
tsx
type NormalizedAlignment = { characters: string[]; // Individual characters (["H","e","l","l","o"]) character_start_times_seconds: number[]; // Start time of each character in seconds character_end_times_seconds: number[]; // End time of each character in seconds};
Arrays are parallel — characters[i] starts at character_start_times_seconds[i] and ends at character_end_times_seconds[i].
LiveContextArgs
Argument shape for addLiveContext() (call mode).
tsx
type LiveContextArgs = { context: string; // non-empty, max 2000 characters update?: boolean; // whether to replace the previously submitted context};
AvatarError
The error type emitted by the SDK.
tsx
type AvatarError = { // --- Branch on these --- code: AvatarErrorCode; fatal: boolean; // Is the session over? retryable: boolean; // Would calling start() again help? // --- Log these; don't render them --- message: string; // Written for you, not your users source: AvatarErrorSource; cause?: unknown;};
Grouped by who fixes it — the only distinction you can act on.
tsx
type AvatarErrorCode = // Your integration — you fix these in your own code. | "SESSION_TOKEN_FETCH_FAILED" | "INVALID_MODE" | "INVALID_INPUT" | "NOT_CONNECTED" // Your user — they must act; retrying alone won't help. | "MIC_PERMISSION_DENIED" // The service — retry, or report to us. | "CONNECTION_FAILED" | "SERVER_ERROR" | "SERVER_CLOSE_REQUESTED" | "AVATAR_LOAD_FAILED" | "BRAIN_ERROR" // Expected lifecycle. | "SESSION_IDLE_TIMEOUT" // Nothing else fit. | "UNKNOWN";
These are deliberately coarse: they split where the remedy splits, and nowhere else. Every transport failure is one CONNECTION_FAILED — which socket call failed is in message and cause, so it never costs you a branch.
AvatarErrorSource
Where an error originated.
tsx
type AvatarErrorSource = "network" | "server" | "sdk";
Avatar props
The <Avatar> component accepts these props (defined inline by the component, not a named export):
tsx
type CameraPreviewCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right";type AvatarProps = { style?: ViewStyle; // from "react-native" loader?: React.ReactNode; // custom loading element errorFallback?: React.ReactNode; // custom error element // Overlay styling hooks captionStyle?: ViewStyle; // shown when transcript.captions is on statusBannerStyle?: ViewStyle; // shown when statusBanner.enabled is on // Camera (perception.camera only) cameraPreviewCorner?: CameraPreviewCorner; // default "bottom-right" hideCameraPreview?: boolean; // discouraged — capture continues either way};
Native takes ViewStyle, not className, and has no picture-in-picture
layout or fit override — both are web-only.
AvatarEventMap
The complete event map — keys are event names, values are handler signatures.
transcript only fires when transcript.enabled is set.
UseAvatarResult
The complete return type of the useAvatar hook.
tsx
interface UseAvatarResult { // --- Paint axis: is there an avatar on screen? --- isReady: boolean; isLoading: boolean; isFailed: boolean; // --- Session axis: is there a live call? --- isIdle: boolean; isConnecting: boolean; isConnected: boolean; // --- Turn state (only meaningful while connected) --- isListening: boolean; isThinking: boolean; isSpeaking: boolean; isResponseSlow: boolean; // this turn is dragging — render your own hint // --- Mute --- isMicMuted: boolean; isSpeakerMuted: boolean; setMicMuted: (muted: boolean) => void; setSpeakerMuted: (muted: boolean) => void; // --- Push to talk --- isPushToTalk: boolean; isTalking: boolean; startTalking: () => void; stopTalking: () => void; // --- Session control --- start(): void; stop(): void; interrupt(): void; stopSpeaking(): void; // --- Mode-specific (undefined in wrong mode) --- play?(job: AvatarSpeech): void; speakText?(sentence: string): void; speakAudio?(audio: ArrayBuffer | Float32Array | Blob): void; addLiveContext?(args: LiveContextArgs): void; // --- Gestures --- triggerAction?: (name: string) => void; availableActions?: string[]; // --- Live data --- error: AvatarError | null; notice?: SessionNotice | null; health?: ConnectionHealth; transcript?: TranscriptEntry[]; avatarId?: string; controls: { enabled: boolean; stopSpeaking?: boolean }; // --- Event subscription --- on<E extends keyof AvatarEventMap>(event: E, handler: AvatarEventMap[E]): void; off<E extends keyof AvatarEventMap>(event: E, handler: AvatarEventMap[E]): void;}
play, speakText, speakAudio, and addLiveContext are marked optional (?) because they return undefined in unsupported modes. Always use optional chaining: speakText?.("hello").