Transcribe audio data to text using on-device Whisper models via ONNX Runtime.
Basic Usage
// Load STT model first
await RunAnywhere . loadSTTModel ( 'sherpa-onnx-whisper-tiny.en' );
// Transcribe audio data (PCM16 at 16kHz mono)
final text = await RunAnywhere . transcribe (audioBytes);
print ( 'Transcription: $ text ' );
With Detailed Result
Get confidence scores and metadata with transcribeWithResult():
final result = await RunAnywhere . transcribeWithResult (audioBytes);
print ( 'Text: ${ result . text } ' );
print ( 'Confidence: ${( result . confidence * 100 ). toStringAsFixed ( 1 )} %' );
print ( 'Duration: ${ result . durationMs } ms' );
if (result.language != null ) {
print ( 'Language: ${ result . language } ' );
}
STTResult
Property Type Description textStringTranscribed text confidencedoubleConfidence score (0.0 to 1.0) durationMsintAudio duration in milliseconds languageString?Detected language code
Setup
1. Register ONNX Backend
import 'package:runanywhere_onnx/runanywhere_onnx.dart' ;
await Onnx . register ();
2. Add STT Model
Onnx . addModel (
id : 'sherpa-onnx-whisper-tiny.en' ,
name : 'Whisper Tiny English' ,
url : 'https://github.com/RunanywhereAI/sherpa-onnx/releases/download/runanywhere-models-v1/sherpa-onnx-whisper-tiny.en.tar.gz' ,
modality : ModelCategory .speechRecognition,
);
3. Download & Load
// Download
await for ( final progress in RunAnywhere . downloadModel ( 'sherpa-onnx-whisper-tiny.en' )) {
print ( ' ${( progress . percentage * 100 ). toStringAsFixed ( 1 )} %' );
if (progress.state.isCompleted) break ;
}
// Load
await RunAnywhere . loadSTTModel ( 'sherpa-onnx-whisper-tiny.en' );
Audio must be in the correct format for accurate transcription.
Property Required Value Format PCM (raw audio) Sample Rate 16,000 Hz (16kHz) Channels 1 (mono) Bit Depth 16-bit
Recording Audio
Use a package like record to capture audio:
import 'package:record/record.dart' ;
final recorder = AudioRecorder ();
// Start recording with correct format
await recorder. start (
const RecordConfig (
encoder : AudioEncoder .pcm16bits,
sampleRate : 16000 ,
numChannels : 1 ,
),
path : tempFilePath,
);
// Stop and get audio
await recorder. stop ();
final audioBytes = await File (tempFilePath). readAsBytes ();
// Transcribe
final text = await RunAnywhere . transcribe (audioBytes);
Available Models
Model ID Size Languages Speed sherpa-onnx-whisper-tiny.en~75MB English Fast sherpa-onnx-whisper-base.en~150MB English Medium sherpa-onnx-whisper-small.en~250MB English Slower sherpa-onnx-whisper-tiny~75MB Multilingual Fast
Complete Example
class TranscriptionDemo extends StatefulWidget {
@override
_TranscriptionDemoState createState () => _TranscriptionDemoState ();
}
class _TranscriptionDemoState extends State < TranscriptionDemo > {
final _recorder = AudioRecorder ();
String _transcription = '' ;
bool _isRecording = false ;
bool _isTranscribing = false ;
Future < void > _toggleRecording () async {
if (_isRecording) {
// Stop and transcribe
final path = await _recorder. stop ();
if (path != null ) {
setState (() {
_isRecording = false ;
_isTranscribing = true ;
});
final audioBytes = await File (path). readAsBytes ();
final text = await RunAnywhere . transcribe (audioBytes);
setState (() {
_transcription = text;
_isTranscribing = false ;
});
}
} else {
// Start recording
if ( await _recorder. hasPermission ()) {
final tempDir = await getTemporaryDirectory ();
final path = ' ${ tempDir . path } /recording.pcm' ;
await _recorder. start (
const RecordConfig (
encoder : AudioEncoder .pcm16bits,
sampleRate : 16000 ,
numChannels : 1 ,
),
path : path,
);
setState (() => _isRecording = true );
}
}
}
@override
Widget build ( BuildContext context) {
return Column (
children : [
Text (_transcription),
ElevatedButton (
onPressed : _isTranscribing ? null : _toggleRecording,
child : Text (_isRecording ? 'Stop' : 'Record' ),
),
if (_isTranscribing) CircularProgressIndicator (),
],
);
}
}
See Also
Streaming STT Real-time transcription
STT Options Configuration options