The Model Download Manager provides utilities for downloading, caching, and managing sherpa-onnx models from the official GitHub releases.
Overview
Models are downloaded from the official k2-fsa/sherpa-onnx releases and stored in the app’s document directory. The manager handles:
- Listing available models from GitHub releases
- Downloading and extracting model archives
- Checksum verification
- Download progress and cancellation
- LRU (Least Recently Used) cache management
- Metadata tracking (download date, last used, disk size)
Model Categories
enum ModelCategory {
Tts = 'tts',
Stt = 'stt',
Vad = 'vad',
Diarization = 'diarization',
Enhancement = 'enhancement',
Separation = 'separation',
}
Core Functions
listModelsByCategory()
List available models for a category (from cache).
function listModelsByCategory<T extends ModelMetaBase>(
category: ModelCategory
): Promise<T[]>
refreshModelsByCategory()
Refresh the list of available models from GitHub.
function refreshModelsByCategory<T extends ModelMetaBase>(
category: ModelCategory,
options?: {
forceRefresh?: boolean;
cacheTtlMinutes?: number;
maxRetries?: number;
signal?: AbortSignal;
}
): Promise<T[]>
downloadModelByCategory()
Download and extract a model.
function downloadModelByCategory<T extends ModelMetaBase>(
category: ModelCategory,
id: string,
options?: {
onProgress?: (progress: DownloadProgress) => void;
overwrite?: boolean;
signal?: AbortSignal;
maxRetries?: number;
onChecksumIssue?: (issue: ChecksumIssue) => Promise<boolean>;
}
): Promise<DownloadResult>
getLocalModelPathByCategory()
Get the local path to a downloaded model.
function getLocalModelPathByCategory(
category: ModelCategory,
id: string
): Promise<string | null>
isModelDownloadedByCategory()
Check if a model is downloaded.
function isModelDownloadedByCategory(
category: ModelCategory,
id: string
): Promise<boolean>
deleteModelByCategory()
Delete a downloaded model.
function deleteModelByCategory(
category: ModelCategory,
id: string
): Promise<void>
listDownloadedModelsByCategory()
List all downloaded models for a category.
function listDownloadedModelsByCategory<T extends ModelMetaBase>(
category: ModelCategory
): Promise<T[]>
Examples
List and Download TTS Models
import {
ModelCategory,
listModelsByCategory,
refreshModelsByCategory,
downloadModelByCategory,
getLocalModelPathByCategory,
} from 'react-native-sherpa-onnx/download';
import type { TtsModelMeta } from 'react-native-sherpa-onnx/download';
// Refresh model list from GitHub
const models = await refreshModelsByCategory<TtsModelMeta>(
ModelCategory.Tts
);
console.log('Available TTS models:', models.length);
// Filter for English VITS models
const englishVits = models.filter(
(m) => m.type === 'vits' && m.languages.includes('en')
);
// Download a model
const modelId = 'vits-piper-en_US-lessac-medium';
const result = await downloadModelByCategory(
ModelCategory.Tts,
modelId,
{
onProgress: (progress) => {
console.log(`Download: ${progress.percent.toFixed(1)}%`);
if (progress.speed) {
const mbps = (progress.speed / 1024 / 1024).toFixed(2);
console.log(`Speed: ${mbps} MB/s`);
}
},
}
);
console.log('Downloaded to:', result.localPath);
// Get path for use with TTS
const modelPath = await getLocalModelPathByCategory(
ModelCategory.Tts,
modelId
);
Download with Progress UI
import { useState } from 'react';
import { ModelCategory, downloadModelByCategory } from 'react-native-sherpa-onnx/download';
function ModelDownloadComponent() {
const [progress, setProgress] = useState(0);
const [phase, setPhase] = useState<'downloading' | 'extracting'>('downloading');
const [isDownloading, setIsDownloading] = useState(false);
const download = async (modelId: string) => {
setIsDownloading(true);
try {
await downloadModelByCategory(
ModelCategory.Tts,
modelId,
{
onProgress: (p) => {
setProgress(p.percent);
setPhase(p.phase || 'downloading');
},
}
);
console.log('Download complete!');
} catch (error) {
console.error('Download failed:', error);
} finally {
setIsDownloading(false);
}
};
return (
<View>
{isDownloading && (
<View>
<Text>{phase}: {progress.toFixed(1)}%</Text>
<ProgressBar progress={progress / 100} />
</View>
)}
</View>
);
}
Download with Cancellation
import { ModelCategory, downloadModelByCategory } from 'react-native-sherpa-onnx/download';
const abortController = new AbortController();
const downloadPromise = downloadModelByCategory(
ModelCategory.Stt,
'sherpa-onnx-whisper-tiny-en',
{
signal: abortController.signal,
onProgress: (progress) => {
console.log(`Progress: ${progress.percent}%`);
},
}
);
// Cancel after 5 seconds
setTimeout(() => {
abortController.abort();
console.log('Download cancelled');
}, 5000);
try {
await downloadPromise;
} catch (error) {
if (error.name === 'AbortError') {
console.log('Download was cancelled');
}
}
LRU Cache Management
import {
ModelCategory,
listDownloadedModelsWithMetadata,
cleanupLeastRecentlyUsed,
} from 'react-native-sherpa-onnx/download';
// List downloaded models with metadata
const models = await listDownloadedModelsWithMetadata(ModelCategory.Tts);
console.log('Downloaded models:');
for (const m of models) {
const sizeMB = ((m.sizeOnDisk || 0) / 1024 / 1024).toFixed(1);
console.log(`${m.model.id}: ${sizeMB} MB, last used: ${m.lastUsed}`);
}
// Clean up old models (keep 3 most recent, delete others)
const deletedIds = await cleanupLeastRecentlyUsed(
ModelCategory.Tts,
{
keepCount: 3,
}
);
console.log('Deleted models:', deletedIds);
// Or free up specific amount of space
const targetBytes = 500 * 1024 * 1024; // 500 MB
await cleanupLeastRecentlyUsed(
ModelCategory.Tts,
{
targetBytes,
keepCount: 1,
}
);
List Downloaded Models
import {
ModelCategory,
listDownloadedModelsByCategory,
isModelDownloadedByCategory,
} from 'react-native-sherpa-onnx/download';
// Get all downloaded TTS models
const downloaded = await listDownloadedModelsByCategory(ModelCategory.Tts);
console.log('Downloaded TTS models:', downloaded.map(m => m.id));
// Check if specific model is downloaded
const isDownloaded = await isModelDownloadedByCategory(
ModelCategory.Tts,
'vits-piper-en_US-lessac-medium'
);
if (isDownloaded) {
console.log('Model ready to use');
}
Subscribe to Events
subscribeDownloadProgress()
Subscribe to download progress events for all downloads.
function subscribeDownloadProgress(
listener: DownloadProgressListener
): () => void
subscribeModelsListUpdated()
Subscribe to model list updates.
function subscribeModelsListUpdated(
listener: ModelsListUpdatedListener
): () => void
Example
import {
subscribeDownloadProgress,
subscribeModelsListUpdated,
} from 'react-native-sherpa-onnx/download';
// Subscribe to download progress
const unsubscribeProgress = subscribeDownloadProgress(
(category, modelId, progress) => {
console.log(`${category}/${modelId}: ${progress.percent}%`);
}
);
// Subscribe to model list updates
const unsubscribeList = subscribeModelsListUpdated(
(category, models) => {
console.log(`${category} models updated:`, models.length);
}
);
// Later: unsubscribe
unsubscribeProgress();
unsubscribeList();
Types
interface TtsModelMeta {
id: string;
displayName: string;
type: TTSModelType | 'unknown';
languages: string[];
quantization: 'fp16' | 'int8' | 'int8-quantized' | 'unknown';
sizeTier: 'tiny' | 'small' | 'medium' | 'large' | 'unknown';
downloadUrl: string;
archiveExt: 'tar.bz2' | 'onnx';
bytes: number;
sha256?: string;
category: ModelCategory.Tts;
}
DownloadProgress
interface DownloadProgress {
bytesDownloaded: number;
totalBytes: number;
percent: number;
phase?: 'downloading' | 'extracting';
speed?: number; // bytes per second
eta?: number; // estimated seconds remaining
}
DownloadResult
interface DownloadResult {
modelId: string;
localPath: string;
}
Validation
The download manager includes built-in validation:
- Checksum verification: SHA-256 checksums from GitHub releases
- File validation: Ensures required model files exist after extraction
- Disk space check: Verifies sufficient space before download
import {
validateChecksum,
validateExtractedFiles,
checkDiskSpace,
} from 'react-native-sherpa-onnx/download';
// Check disk space
const spaceCheck = await checkDiskSpace(500 * 1024 * 1024); // 500 MB
if (!spaceCheck.success) {
console.error('Insufficient space:', spaceCheck.message);
}
// Validate checksum
const checksumResult = await validateChecksum(
'/path/to/model.tar.bz2',
'expected_sha256_hash'
);
if (!checksumResult.success) {
console.error('Checksum failed:', checksumResult.message);
}
Utility Functions
Extract a .tar.bz2 archive file (requires libarchive).
function extractTarBz2(
sourcePath: string,
targetPath: string,
force?: boolean,
onProgress?: (event: ExtractProgressEvent) => void
): Promise<void>
Absolute path to the .tar.bz2 file
Absolute path to extract to
If true, overwrite existing files. Default: false
onProgress
(event: ExtractProgressEvent) => void
Progress callback with bytesExtracted and totalBytes
If libarchive is disabled in your build (see Disable Libarchive), this function will reject with an error.
Example:
import { extractTarBz2 } from 'react-native-sherpa-onnx/download';
await extractTarBz2(
'/path/to/model.tar.bz2',
'/path/to/models/',
false,
(event) => {
console.log(`Extracted ${event.bytesExtracted} / ${event.totalBytes}`);
}
);
Cancel an ongoing extraction.
function cancelExtractTarBz2(): void
computeFileSha256()
Compute SHA256 checksum of a file.
function computeFileSha256(
filePath: string
): Promise<string>
Absolute path to the file
Returns a promise resolving to the lowercase hex SHA256 hash.
Example:
import { computeFileSha256 } from 'react-native-sherpa-onnx/download';
const hash = await computeFileSha256('/path/to/model.tar.bz2');
console.log('SHA256:', hash);
See Also