Skip to main content
Helper functions for working with audio in React Native Sherpa-ONNX. These utilities handle TTS audio output, file conversion, Android Storage Access Framework (SAF), and sharing.
Import Paths:
  • TTS audio helpers: import { saveAudioToFile, shareAudioFile } from 'react-native-sherpa-onnx/tts'
  • Audio conversion: import { convertAudioToFormat } from 'react-native-sherpa-onnx/audio'

File Operations

saveAudioToFile()

Save generated TTS audio to a WAV file.
function saveAudioToFile(
  audio: GeneratedAudio,
  filePath: string
): Promise<string>
audio
GeneratedAudio
required
Generated audio object from generateSpeech() or generateSpeechWithTimestamps()Properties:
  • samples: Float32Array of audio samples
  • sampleRate: Sample rate in Hz (e.g., 22050, 24000)
filePath
string
required
Absolute path where the WAV file should be saved
path
Promise<string>
The absolute path of the saved file
Example:
import { createTTS, saveAudioToFile } from 'react-native-sherpa-onnx';
import { DocumentDirectoryPath } from '@dr.pogodin/react-native-fs';

const tts = await createTTS({
  modelPath: { type: 'asset', path: 'models/vits-piper-en' },
  modelType: 'vits',
});

const audio = await tts.generateSpeech('Hello, world!');
const outputPath = `${DocumentDirectoryPath}/output.wav`;
const savedPath = await saveAudioToFile(audio, outputPath);
console.log('Audio saved to:', savedPath);

saveAudioToContentUri()

Save generated TTS audio to a WAV file via Android Storage Access Framework (SAF).
function saveAudioToContentUri(
  audio: GeneratedAudio,
  directoryUri: string,
  filename: string
): Promise<string>
audio
GeneratedAudio
required
Generated audio object from generateSpeech()
directoryUri
string
required
SAF directory content URI (obtained from react-native-document-picker or react-native-fs)
filename
string
required
Filename for the WAV file (e.g., "speech.wav")
uri
Promise<string>
Content URI of the saved file
This function is Android-only. Use saveAudioToFile() on iOS or when working with app-internal storage.
Example:
import { createTTS, saveAudioToContentUri } from 'react-native-sherpa-onnx';
import DocumentPicker from 'react-native-document-picker';

// Let user pick a directory
const result = await DocumentPicker.pickDirectory();
if (!result) return;

const tts = await createTTS({
  modelPath: { type: 'asset', path: 'models/vits-piper-en' },
  modelType: 'vits',
});

const audio = await tts.generateSpeech('Hello, Android!');
const uri = await saveAudioToContentUri(
  audio,
  result.uri,
  'output.wav'
);
console.log('Audio saved to content URI:', uri);

copyContentUriToCache()

Copy a file from an Android SAF content URI to app cache for local playback.
function copyContentUriToCache(
  fileUri: string,
  filename: string
): Promise<string>
fileUri
string
required
SAF content URI of the source file
filename
string
required
Filename for the cached copy
path
Promise<string>
Absolute path of the cached file
This function is Android-only. Use this when you need to play audio from a content URI with media players that don’t support content URIs.
Example:
import { saveAudioToContentUri, copyContentUriToCache } from 'react-native-sherpa-onnx';
import Sound from 'react-native-sound';

const tts = await createTTS({ modelPath: { type: 'asset', path: 'models/vits-piper-en' } });
const audio = await tts.generateSpeech('Test audio');

// Save to user-selected directory
const contentUri = await saveAudioToContentUri(audio, directoryUri, 'test.wav');

// Copy to cache for playback
const cachePath = await copyContentUriToCache(contentUri, 'test.wav');

// Play the cached file
const sound = new Sound(cachePath, '', (error) => {
  if (!error) sound.play();
});

saveTextToContentUri()

Save a text file via Android Storage Access Framework (SAF).
function saveTextToContentUri(
  text: string,
  directoryUri: string,
  filename: string,
  mimeType?: string
): Promise<string>
text
string
required
Text content to save
directoryUri
string
required
SAF directory content URI
filename
string
required
Filename for the text file (e.g., "transcript.txt")
mimeType
string
default:"'text/plain'"
MIME type of the text file
uri
Promise<string>
Content URI of the saved file
This function is Android-only. Useful for saving transcripts or subtitles alongside audio files.
Example:
import { saveTextToContentUri } from 'react-native-sherpa-onnx/tts';
import DocumentPicker from 'react-native-document-picker';

// Let user pick a directory
const result = await DocumentPicker.pickDirectory();
if (!result) return;

const transcript = "This is the transcript of the audio.";
const uri = await saveTextToContentUri(
  transcript,
  result.uri,
  'transcript.txt',
  'text/plain'
);
console.log('Transcript saved to:', uri);

Sharing

shareAudioFile()

Share a TTS audio file using the system share sheet.
function shareAudioFile(
  fileUri: string,
  mimeType?: string
): Promise<void>
fileUri
string
required
File path or content URI to share
  • iOS: Absolute file path
  • Android: File path or content URI (e.g., from saveAudioToContentUri())
mimeType
string
default:"'audio/wav'"
MIME type of the audio file
void
Promise<void>
Resolves when the share sheet is dismissed
Example:
import { createTTS, saveAudioToFile, shareAudioFile } from 'react-native-sherpa-onnx';
import { DocumentDirectoryPath } from '@dr.pogodin/react-native-fs';

const tts = await createTTS({
  modelPath: { type: 'asset', path: 'models/vits-piper-en' },
  modelType: 'vits',
});

const audio = await tts.generateSpeech('Share this audio');
const filePath = `${DocumentDirectoryPath}/share-audio.wav`;
await saveAudioToFile(audio, filePath);

// Share via system share sheet
await shareAudioFile(filePath);
Android SAF Example:
import { saveAudioToContentUri, shareAudioFile } from 'react-native-sherpa-onnx';

const audio = await tts.generateSpeech('Share via content URI');
const contentUri = await saveAudioToContentUri(audio, directoryUri, 'share.wav');

// Share content URI (Android only)
await shareAudioFile(contentUri, 'audio/wav');

Audio Conversion

convertAudioToFormat()

Convert audio files between different formats (requires FFmpeg on Android).
function convertAudioToFormat(
  inputPath: string,
  outputPath: string,
  format: string,
  outputSampleRateHz?: number
): Promise<void>
inputPath
string
required
Absolute path to the input audio file
outputPath
string
required
Absolute path for the output file
format
string
required
Output format: "mp3", "flac", "wav", etc.
outputSampleRateHz
number
default:"44100"
Sample rate for output (MP3: 32000, 44100, or 48000; WAV: always 16000 mono for sherpa-onnx)
This function requires FFmpeg prebuilts on Android. See Disable FFmpeg if you need to reduce app size.
Example:
import { convertAudioToFormat } from 'react-native-sherpa-onnx/audio';
import { DocumentDirectoryPath } from '@dr.pogodin/react-native-fs';

const inputPath = `${DocumentDirectoryPath}/recording.m4a`;
const outputPath = `${DocumentDirectoryPath}/recording.mp3`;

await convertAudioToFormat(inputPath, outputPath, 'mp3', 44100);
console.log('Converted to MP3');

convertAudioToWav16k()

Convert any audio file to WAV format (16 kHz, mono, 16-bit PCM) suitable for STT.
function convertAudioToWav16k(
  inputPath: string,
  outputPath: string
): Promise<void>
inputPath
string
required
Absolute path to the input audio file (any format supported by FFmpeg)
outputPath
string
required
Absolute path for the output WAV file
This function requires FFmpeg prebuilts on Android.
Use this function to prepare audio files for speech-to-text. Sherpa-ONNX expects 16 kHz mono audio for optimal STT performance.
Example:
import { convertAudioToWav16k } from 'react-native-sherpa-onnx/audio';
import { createSTT } from 'react-native-sherpa-onnx/stt';
import { DocumentDirectoryPath } from '@dr.pogodin/react-native-fs';

// Convert various audio formats to STT-compatible WAV
const inputPath = `${DocumentDirectoryPath}/recording.mp3`;
const wavPath = `${DocumentDirectoryPath}/recording.wav`;

await convertAudioToWav16k(inputPath, wavPath);

// Now transcribe
const stt = await createSTT({
  modelPath: { type: 'asset', path: 'models/whisper-tiny' },
  modelType: 'whisper',
});

const result = await stt.transcribeFile(wavPath);
console.log('Transcription:', result.text);
Use Cases:
  • Prepare audio for STT (convert MP3, M4A, FLAC → WAV 16kHz)
  • Normalize audio sample rates before transcription
  • Convert recorded audio to STT-compatible format

Type Definitions

GeneratedAudio

Generated audio data structure:
type GeneratedAudio = {
  samples: Float32Array;  // Audio samples in floating-point format
  sampleRate: number;     // Sample rate in Hz (e.g., 22050, 24000)
};

GeneratedAudioWithTimestamps

Extended audio data with word/phoneme timestamps:
type GeneratedAudioWithTimestamps = {
  samples: Float32Array;
  sampleRate: number;
  timestamps: TtsSubtitleItem[]; // Word/phoneme timing information
};

type TtsSubtitleItem = {
  text: string;      // Word or phoneme text
  start: number;     // Start time in seconds
  end: number;       // End time in seconds
};

Platform Considerations

iOS

  • Use saveAudioToFile() with paths from DocumentDirectoryPath or CachesDirectoryPath
  • saveAudioToContentUri() is not available
  • copyContentUriToCache() is not available
  • shareAudioFile() uses UIActivityViewController

Android

  • saveAudioToFile() works with internal storage paths
  • saveAudioToContentUri() enables saving to external storage via SAF (SD card, Downloads, etc.)
  • copyContentUriToCache() bridges content URIs to file paths
  • shareAudioFile() supports both file paths and content URIs via Intent.ACTION_SEND

Best Practices

  1. Use appropriate storage based on use case:
    • Internal storage (saveAudioToFile): Temporary audio, app-only access
    • SAF (saveAudioToContentUri): User-selected location, persistent storage
  2. Handle platform differences:
    import { Platform } from 'react-native';
    
    if (Platform.OS === 'android') {
      // Use SAF for external storage
      await saveAudioToContentUri(audio, directoryUri, 'audio.wav');
    } else {
      // Use file path on iOS
      await saveAudioToFile(audio, `${DocumentDirectoryPath}/audio.wav`);
    }
    
  3. Clean up temporary files:
    import { unlink } from '@dr.pogodin/react-native-fs';
    
    const tempPath = `${CachesDirectoryPath}/temp.wav`;
    await saveAudioToFile(audio, tempPath);
    await shareAudioFile(tempPath);
    
    // Clean up after sharing
    await unlink(tempPath);
    
  4. Validate file paths:
    import { exists } from '@dr.pogodin/react-native-fs';
    
    const path = await saveAudioToFile(audio, outputPath);
    const fileExists = await exists(path);
    if (!fileExists) {
      throw new Error('Failed to save audio file');
    }
    
  5. Use descriptive filenames:
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const filename = `tts-output-${timestamp}.wav`;
    await saveAudioToFile(audio, `${DocumentDirectoryPath}/${filename}`);
    

Error Handling

try {
  const audio = await tts.generateSpeech('Hello');
  const path = await saveAudioToFile(
    audio,
    `${DocumentDirectoryPath}/output.wav`
  );
  console.log('Success:', path);
} catch (error) {
  if (error.message.includes('No such file or directory')) {
    console.error('Invalid file path');
  } else if (error.message.includes('Permission denied')) {
    console.error('Storage permission required');
  } else {
    console.error('Failed to save audio:', error);
  }
}

Build docs developers (and LLMs) love