Skip to main content
This guide helps you migrate from version 0.2.x to 0.3.0 of react-native-sherpa-onnx. Version 0.3.0 introduces significant improvements including full iOS support, better performance, and ~95% size reduction, but requires code changes.

Overview

Version 0.3.0 introduces:
  • Instance-based API (TTS + STT)
  • Improved return types and type safety
  • Model-specific options structure
  • Renamed types and methods
Breaking Changes: This release changes the public API. Please follow all migration steps before upgrading.

Instance-based API (TTS + STT)

1

Understanding the Change

TTS and STT now use an instance-based factory pattern instead of module-level singletons. Each call to createTTS() / createSTT() returns an independent engine instance.Key requirement: You must call .destroy() when done to free native resources.
2

Migrate TTS Code

Before (0.2.x):
initializeTTS({ modelPath: { type: 'asset', path: 'models/vits' } });
const audio = await generateSpeech('Hello');
await unloadTTS();
After (0.3.0):
const tts = await createTTS({ modelPath: { type: 'asset', path: 'models/vits' } });
const audio = await tts.generateSpeech('Hello');
await tts.destroy();
3

Migrate STT Code

Before (0.2.x):
await initializeSTT({ modelPath: { type: 'asset', path: 'models/whisper' } });
const result = await transcribeFile('/audio.wav');
await unloadSTT();
After (0.3.0):
const stt = await createSTT({ modelPath: { type: 'asset', path: 'models/whisper' } });
const result = await stt.transcribeFile('/audio.wav');
await stt.destroy();

Speech-to-Text (STT) Changes

Return Type Changes

transcribeFile now returns a detailed object instead of just a string:
- const text: string = await transcribeFile(path);
+ const result: SttRecognitionResult = await stt.transcribeFile(path);
+ const text = result.text;
New return type structure:
interface SttRecognitionResult {
  text: string;           // Transcribed text
  tokens: string[];       // Token sequence
  timestamps: number[];   // Timestamp per token
  lang: string;          // Detected language (if supported)
  emotion: string;       // Emotion tag (if supported)
  event: string;         // Event tag (if supported)
  durations: number[];   // Duration info
}
If you only need the text, use result.text to get the transcription string.

Hotwords Support

initializeSTT now supports two additional optional options:
await createSTT({
  modelPath: { type: 'asset', path: 'models/whisper' },
  hotwordsFile: '/path/to/hotwords.txt',  // NEW
  hotwordsScore: 1.5,                      // NEW
});

Deprecated Types

- TranscriptionResult  // REMOVED
+ SttRecognitionResult  // Use this instead

Native Method Renames

If you call the TurboModule directly, methods were renamed:
- initializeSherpaOnnx
+ initializeStt

- unloadSherpaOnnx
+ unloadStt

Text-to-Speech (TTS) Changes

Model Options Structure

Model-specific options (noise scales, length scale) now use a nested modelOptions structure instead of flat properties.
initializeTTS({
  modelPath: { type: 'asset', path: 'models/vits' },
  modelType: 'vits',
  noiseScale: 0.667,
  noiseScaleW: 0.8,
  lengthScale: 1.0
});

Update Parameters

The updateParams method also uses the new structure:
updateTtsParams({
  noiseScale: 0.7,
  lengthScale: 1.2
});

New Model-Specific Types

The following types are now exported:
import type {
  TtsModelOptions,
  TtsVitsModelOptions,
  TtsMatchaModelOptions,
  TtsKokoroModelOptions,
  TtsKittenModelOptions,
  TtsPocketModelOptions
} from 'react-native-sherpa-onnx/tts';

Instance Methods and TurboModule

If you call the TurboModule directly, all instance-bound methods now take instanceId as the first parameter:
// Instance methods
tts.generateSpeech(text)      // High-level API
tts.generateSpeechStream()     // High-level API
tts.destroy()                  // High-level API

// Direct TurboModule (advanced)
module.generateSpeech(instanceId, text)  // Low-level

Deprecated Types

- SynthesisOptions    // REMOVED
+ TtsGenerationOptions // Use this instead

Complete Migration Example

Before (0.2.x):
import { initializeSTT, transcribeFile, unloadSTT } from 'react-native-sherpa-onnx/stt';

async function transcribeAudio(audioPath: string) {
  await initializeSTT({
    modelPath: { type: 'asset', path: 'models/whisper-tiny' },
    modelType: 'whisper'
  });
  
  const text = await transcribeFile(audioPath);
  console.log('Transcription:', text);
  
  await unloadSTT();
  return text;
}
After (0.3.0):
import { createSTT } from 'react-native-sherpa-onnx/stt';

async function transcribeAudio(audioPath: string) {
  const stt = await createSTT({
    modelPath: { type: 'asset', path: 'models/whisper-tiny' },
    modelType: 'whisper'
  });
  
  try {
    const result = await stt.transcribeFile(audioPath);
    console.log('Transcription:', result.text);
    console.log('Language:', result.lang);
    return result.text;
  } finally {
    await stt.destroy(); // Always cleanup
  }
}

Common Patterns

Managing Multiple Instances

import { createSTT, createTTS } from 'react-native-sherpa-onnx';

class SpeechManager {
  private stt: SttEngine | null = null;
  private tts: TtsEngine | null = null;

  async initialize() {
    this.stt = await createSTT({
      modelPath: { type: 'asset', path: 'models/whisper' },
      modelType: 'auto'
    });

    this.tts = await createTTS({
      modelPath: { type: 'asset', path: 'models/vits' },
      modelType: 'auto'
    });
  }

  async cleanup() {
    if (this.stt) {
      await this.stt.destroy();
      this.stt = null;
    }
    if (this.tts) {
      await this.tts.destroy();
      this.tts = null;
    }
  }
}

React Hook Pattern

import { useEffect, useRef } from 'react';
import { createSTT } from 'react-native-sherpa-onnx/stt';

function useSpeechRecognition() {
  const sttRef = useRef<SttEngine | null>(null);

  useEffect(() => {
    let mounted = true;

    async function init() {
      const stt = await createSTT({
        modelPath: { type: 'asset', path: 'models/whisper' },
        modelType: 'auto'
      });
      
      if (mounted) {
        sttRef.current = stt;
      } else {
        await stt.destroy();
      }
    }

    init();

    return () => {
      mounted = false;
      if (sttRef.current) {
        sttRef.current.destroy();
      }
    };
  }, []);

  return sttRef.current;
}

Need Help?

If you encounter issues during migration:
  1. Check the API Reference for detailed method signatures
  2. Review Troubleshooting for common issues
  3. See Examples for working code samples
  4. Open an issue on GitHub

Build docs developers (and LLMs) love