Two migrations live here:Documentation Index
Fetch the complete documentation index at: https://docs.mascot.bot/llms.txt
Use this file to discover all available pages before exploring further.
- 0.2.x → 0.3.0 — current pre-release cutover. Package scope rename
- symbol consolidation (single Provider, single mount component). Most readers want this.
- Legacy → 0.2.x — older architectural migration (server-side visemes → on-device WebAssembly). Kept for integrators on the pre-0.2 SDK.
0.2.x → 0.3.0
The 0.3.0 release unifies SDK naming across the package scope and the React component surface. Hard cutover — no deprecated aliases. The bytes computing visemes are unchanged; only names and the mount shape moved.Package scope
.npmrc
lipsync-native → @mascotbot/native and
lipsync-react-native → @mascotbot/react-native for RN integrators.
React mount — one Provider, one component
<MascotRive /> (or a loading slot) inside
<MascotClient>, pass those as children of <Mascot> instead —
they take over from the default canvas:
Symbol rename — quick reference
| 0.2.x | 0.3.0 | Notes |
|---|---|---|
<LipsyncProvider> | <MascotProvider> | Top-level provider; takes apiKey |
<MascotProvider> (empty Rive marker) | gone | Merged into the top-level |
<MascotClient> + <MascotRive /> | <Mascot> | Single component; renders canvas by default. <MascotRive /> stays as an escape hatch |
useLipsync() | useMascot() | Same return shape |
MascotLipsyncClient | LipsyncClient | Class — package scope provides brand |
MascotLipsyncConfig | LipsyncConfig | Type |
LipsyncContextValue | MascotContextValue | Type returned by useMascot() |
MascotClientContext / MascotClientContextType / MascotClientProps | MascotContext / MascotContextType / MascotProps | Component renamed → matching types |
lipsync here names
what the thing is, not who ships it):
useProcessAudio(url)useLipsyncStream({ source })useMascotRive()/useMascotInputs()/useMascotPlayback()LipsyncError/LipsyncStatus/LipsyncLoggerLipsyncStreamSource/LipsyncStreamFrameLicenseError/NetworkError/EngineError/RefusedErrorVisemeTimeline/VisemeCue/MascotPlayback(the class) /NaturalLipSync*
Migration steps (0.2.x → 0.3.0)
Update .npmrc + package.json
Change
@mascotbot-sdk:registry=… to @mascotbot:registry=…, then
rewrite the four dep names. pnpm install --force after — pnpm
caches tarballs by hash, the new scope needs a fresh resolve.Run the rename grep
useLipsyncStream,
LipsyncError, etc. are intentionally preserved — they survive
because the word lipsync precisely describes what they are.Collapse the Provider + Mascot mount
<LipsyncProvider><MascotProvider>… → single <MascotProvider apiKey>.
<MascotClient src><MascotRive /></MascotClient> → <Mascot src />
if you don’t need a custom layout slot. If you do, change the tag
name from MascotClient to Mascot and keep the children.Legacy → 0.2.x
The 0.2.x SDK was a new architecture, not a renamed release. If you integrated a pre-0.2 build, the changes below still apply (cascade 0.2.x → 0.3.0 from the section above on top).What changed, conceptually
| Then (legacy) | Now (0.2.x+) |
|---|---|
One legacy @mascotbot/react package (pre-0.2) | @mascotbot/core + @mascotbot/react, each with a /rive subpath |
Visemes computed server-side and streamed to the client (REST /v1/visemes, SSE, a Mascot Bot WebSocket proxy, “viseme injection”) | Visemes computed by the SDK on-device. No proxy, no REST viseme API, no SSE viseme protocol |
Provider-specific hooks (useMascotElevenlabs, useMascotLiveAPI, useMascotOpenAI) and a TTS hook (useMascotSpeech) | One realtime contract: tap the assistant’s audio into useLipsyncStream({ source: { kind: "mediaStream", stream } }). TTS server returns audio only; the SDK does the lip sync |
getSignedUrl proxy that injected visemes | Provider wired with its own official SDK; server mints only a short-lived provider credential |
result.argmax per-frame array | result.timeline — a serializable, versioned VisemeTimeline |
Private-registry .tgz install | Private npm registry npm.mascot.bot with an .npmrc token |
Symbol map (legacy → 0.2.x — then add the 0.3.0 column above)
| Legacy | 0.2.x replacement |
|---|---|
Legacy @mascotbot/react (pre-0.2) | @mascotbot/react + @mascotbot/react/rive (0.3.0 names) |
useMascot() | useMascotRive() + useMascotInputs() (split the grab-bag — rive/render from the first, custom/has/riveInputs from the second) |
useMascotClient() | useMascotRive() + useMascotInputs() |
useRiveInputs() | useMascotInputs() |
useMascotSpeech() | Server route returns audio → createPCMStreamPlayer + useLipsyncStream. See Realtime overview |
useMascotElevenlabs() | ElevenLabs guide — own SDK + audio tap |
useMascotLiveAPI() | Gemini Live guide |
useMascotOpenAI() | OpenAI Realtime guide |
gesture: true (auto-fire at utterance start) | The auto-fire is gone — the SDK never drives the gesture input. The built-in stress emphasis is useMascotPlayback().stress([{ offset, stress }]). A separate custom gesture trigger input is consumer-fired via useMascotInputs().custom.gesture.fire() — declare it on <Mascot inputs={["gesture", ...]}> first |
useMicLipsync() | useLipsyncStream({ source: { kind: "mic" } }) |
useStreamingLipsync() | useLipsyncStream({ source: { kind: "manual" } }) |
useMediaStreamLipsync() | useLipsyncStream({ source: { kind: "mediaStream", stream } }) |
playback.add(visemes) | playback.pushVisemes(cues) (streaming) or playback.setTimeline(tl) (offline) |
loadPrefetchedData(...) | Persist a VisemeTimeline JSON; replay via parseTimeline + setTimeline. See Offline lip sync |
result.argmax | result.timeline (a VisemeTimeline) |
rive.stateMachineInputs(...) introspection for presence | useMascotInputs().has(name) / hasRiveInput(rive, name) |
Mascot Bot proxy / get-signed-url / /v1/visemes | Removed — hybrid architecture; license init + refresh against license.mascot.bot. |
Hooks are not reference-stable
LegacyuseMascot() returned a memoised, stable object;
useMascotRive() / useMascotInputs() return a fresh wrapper every
render.
- Putting their return (
custom,has, the whole handle) in auseEffect/useCallbackdependency array re-runs it every render — e.g. a Rive event listener that re-binds ~60×/s. Capture what you need in auseRefand depend only on the stableriveinstance (stable once loaded).riveInputsidentity is stable, but the wrapper object andhasare fresh per render — so this rule applies to them.
Next
Quickstart
The current happy path.
Realtime overview
Provider wiring.
Troubleshooting
Post-migration issues.