1. Mount the provider
<MascotProvider> initializes a single LipsyncClient for your app
and exposes it through context.
useMascot() gives you the client and status, and
useProcessAudio() fetches a URL, decodes, resamples to 16 kHz, and runs
inference once:
result.timeline is a VisemeTimeline —
hand it to playback below, or JSON.stringify it to persist and replay later
with zero reprocessing.
2. Drive a Rive avatar
Wire the timeline into a Rive avatar’s mouth state machine with the/rive
subpath:
Rive avatar requirements
If you author your own.riv file:
| Element | Requirement |
|---|---|
| Artboard name | Character |
| State machine name | mascotStateMachine |
| Mouth inputs | Number inputs 100–118 (viseme ids) |
| Emotion inputs (optional) | is_speaking, eyes_smile |
| Stress input (optional) | stress (number) |
rive instance
(useMascotRive().rive) — see Rive co-existence.
Or skip authoring entirely and use a ready-made mascot.
3. Live microphone input
Drive the avatar from the user’s microphone in real time withuseLipsyncStream:
workletUrl only if your CSP forbids
worker-src blob:. The same hook handles realtime AI providers via
source: { kind: "mediaStream", stream } — see
Realtime providers.
4. Vanilla JavaScript
Not using React? Use@mascotbot/core directly:
@mascotbot/core/rive — see Core SDK.
Error handling
useMascot() exposes status and error. Branch on error.code, not the
subclass:
Next
Offline lip sync
Generate → persist → replay.
React hooks
The full hook reference.
Realtime providers
OpenAI, Gemini, ElevenLabs.