Skip to content

Quickstart

This page walks the shortest path from an empty Expo app to a local WAV file. It assumes you already have private npm access; if not, start with Installation & prerequisites.

1. Install both packages

bash
npx expo install @optimalai/react-native@beta
npx @optimalai/model-tools@beta add kokoro-82m-v1.1-zh-int8

The second command downloads the model kit, verifies every file against its recorded byte length and SHA-256, and generates optimalai-models.ts next to your app code. See Model preparation.

2. Register the plugin and the Metro asset types

In app.json:

json
{ "expo": { "plugins": ["@optimalai/react-native"] } }

In metro.config.js:

js
const { getDefaultConfig } = require("expo/metro-config");
const { withOptimalAI } = require("@optimalai/react-native/metro");

module.exports = withOptimalAI(getDefaultConfig(__dirname));

Then rebuild your Development Build. Expo Go cannot load this SDK — native ONNX Runtime code has to be compiled into the app. Details in Expo & Metro setup.

3. Synthesize

ts
import { createTts } from "@optimalai/react-native";
import { kokoroZhInt8 } from "./optimalai-models";

const tts = createTts({
  model: kokoroZhInt8,
  voiceId: "zf_001",
  numThreads: 4,
});

await tts.load();
const result = await tts.synthesizeToFile({
  text: "你好,Hello world.",
  voiceId: "af_maple", // Optional: overrides the default voice for this WAV.
});
console.log(result.fileUri);

result.fileUri is a file:// URI pointing at a 24 kHz, 16-bit, mono WAV in your app's cache directory.

4. Play it yourself

The SDK does not play audio. Hand the URI to whatever player you already use:

ts
import { useAudioPlayer } from "expo-audio";

const player = useAudioPlayer(null);
player.replace(result.fileUri);
player.play();

5. Release the model when you are done

ts
await tts.reset();

The shape of the whole thing

StepCallNotes
CreatecreateTts({ model, voiceId, numThreads? })Cheap; does not touch the native model yet.
Loadawait tts.load()Cold start. Resolves the asset URIs and opens the ONNX session.
Synthesizeawait tts.synthesizeToFile({ text, voiceId?, outputPath?, speed? })One at a time per client.
Inspecttts.status()unloaded / loading / ready / synthesizing / failed.
Releaseawait tts.reset()Frees the session and returns to unloaded.

Where to go next