Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
4e0bdb6
Added probabilities to OnlineRecognizerResult
Dokotela Aug 24, 2025
1e5111e
maybe if I spell it right and in the right place
Dokotela Aug 24, 2025
b188759
flutter updates
Dokotela Sep 23, 2025
77dde1f
core probability files
Dokotela Sep 23, 2025
2e8033b
whisper probabilities
Dokotela Sep 23, 2025
2dc62a4
canary confidence scores
Dokotela Sep 23, 2025
0ad50a9
moonshine confidence scores
Dokotela Sep 23, 2025
fd13598
Merge branch 'master' of https://github.com/Dokotela/sherpa-onnx
Dokotela Sep 23, 2025
49f1919
streaming nemo confidences
Dokotela Sep 25, 2025
634cfd8
Merge branch 'master' of https://github.com/k2-fsa/sherpa-onnx
Dokotela Sep 25, 2025
cabd408
Removed debug statements
Dokotela Sep 25, 2025
06c97ae
Matching original formatting
Dokotela Sep 25, 2025
14ffa69
Renamed probability variable, removed word-level probability
Dokotela Sep 25, 2025
2620453
token_probs -> token_log_probs
Dokotela Sep 25, 2025
ae4b752
Adding full vocab log probs
Dokotela Oct 9, 2025
2a674d8
Merge branch 'k2-fsa:master' into master
Dokotela Oct 9, 2025
a4ac5f8
Merge branch 'master' of https://github.com/Dokotela/sherpa-onnx
Dokotela Oct 9, 2025
abe6179
Streaming does seem to have probabilities now
Dokotela Oct 10, 2025
44a8571
don't remember if I needed this
Dokotela Dec 1, 2025
1a85fd4
Merge upstream/master: Sync with k2-fsa/sherpa-onnx while preserving …
Dokotela Dec 14, 2025
51c97d1
Making as few adjustments as I can
Dokotela Dec 14, 2025
fbc1f66
Straightforward fixes to Gemini Code's PR Comments
Dokotela Dec 14, 2025
ce7f975
Should be cleaned now
Dokotela Dec 14, 2025
ff6bd92
Add guard for invalid temperature_scale in NeMo decoder
Dokotela Dec 14, 2025
d4e3e9c
Fix vocab_log_probs alignment: use idx directly instead of separate c…
Dokotela Dec 14, 2025
f895643
Two more fixes
Dokotela Dec 14, 2025
c789d10
Optimize decoders and fix alignment per CodeRabbit review
Dokotela Dec 15, 2025
e10e710
Added imports, cleanup unused includes, clarified comments, moved vec…
Dokotela Dec 15, 2025
7d52885
Fix NeMo decoder: copy logits before modifying (issue on MacOS)
Dokotela Dec 15, 2025
70e305c
Added a comment clarifying that vocab_log_probs includes the blank pe…
Dokotela Dec 15, 2025
7aabaf9
Code rabbit is picky
Dokotela Dec 15, 2025
bc29883
unclear if this will work or not
Dokotela Dec 16, 2025
cb3434b
reverting back to the correct url
Dokotela Dec 16, 2025
c6ad516
trigger ci
Dokotela Dec 16, 2025
2cdb186
Merge branch 'master' into master
Dokotela Dec 27, 2025
53fef2f
Merge branch 'master' into master
Dokotela Jan 7, 2026
9233160
Fix CodeRabbit review issues: JSON serialization, type conversion, an…
Dokotela Jan 11, 2026
e818e25
Merge branch 'master' of https://github.com/Dokotela/sherpa-onnx
Dokotela Jan 11, 2026
83ba9ff
Apply CodeRabbit nitpick suggestions for consistency
Dokotela Jan 12, 2026
80b6f80
Fix struct redefinition error in offline-whisper-model-config.h
Dokotela Jan 12, 2026
67970fb
Add MedASR CTC model support to Flutter bindings
Dokotela Jan 12, 2026
2316c5a
Fix medasr-ctc example to use local sherpa_onnx package
Dokotela Jan 12, 2026
f30966f
Revert medasr example to use published sherpa_onnx package
Dokotela Jan 12, 2026
f034396
Merge upstream/master (v1.12.21)
Dokotela Jan 12, 2026
6f35262
Fix TODO comment to reference Vocabulary Log Probabilities API
Dokotela Jan 12, 2026
ce02979
Merge upstream/master: sync with latest changes (v1.12.23)
Dokotela Jan 22, 2026
b0d37fe
Fix merge conflicts in offline_recognizer.dart
Dokotela Jan 22, 2026
724ee36
Merge upstream/master: sync with k2-fsa/sherpa-onnx v1.12.29
Dokotela Mar 13, 2026
06c2c17
Add per-token log probabilities to CTC greedy search decoder
Dokotela Mar 13, 2026
496f0c4
Fix native memory leak and DRY up JSON parsing in OfflineRecognizer
Dokotela Mar 13, 2026
882a858
Remove formatting noise from diff to keep PR reviewable
Dokotela Mar 13, 2026
c86bab9
Fix bugs in vocab_log_probs propagation and numerical precision
Dokotela Mar 13, 2026
402379b
Revert unrelated merge artifacts to sync with upstream
Dokotela Mar 13, 2026
3052e77
Remove formatting-only changes to keep PR diff clean
Dokotela Mar 13, 2026
22ead23
Fix three bugs in vocab_log_probs feature
Dokotela Mar 13, 2026
2bcdf7a
Fix minor issues in vocab_log_probs and bindings
Dokotela Mar 13, 2026
caf7d0e
Fix remaining merge artifacts missed in initial cleanup
Dokotela Mar 13, 2026
98e0a3e
Remove stray blank line in canary RunEncoder
Dokotela Mar 13, 2026
0466c61
Merge remote-tracking branch 'upstream/master'
Dokotela Mar 13, 2026
95c902b
Use fromJson in online getResult for consistency and null safety
Dokotela Mar 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 27 additions & 23 deletions flutter/sherpa_onnx/lib/src/offline_recognizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ class OfflineRecognizerResult {
OfflineRecognizerResult({
required this.text,
required this.tokens,
required this.tokenLogProbs,
required this.timestamps,
required this.lang,
required this.emotion,
Expand All @@ -746,6 +747,10 @@ class OfflineRecognizerResult {
return OfflineRecognizerResult(
text: json['text'] as String? ?? '',
tokens: (json['tokens'] as List?)?.map((e) => e as String).toList() ?? [],
tokenLogProbs: (json['token_log_probs'] as List?)
?.map((e) => (e as num).toDouble())
.toList() ??
[],
timestamps:
(json['timestamps'] as List?)
?.map((e) => (e as num).toDouble())
Expand All @@ -759,12 +764,13 @@ class OfflineRecognizerResult {

@override
String toString() {
return 'OfflineRecognizerResult(text: $text, tokens: $tokens, timestamps: $timestamps, lang: $lang, emotion: $emotion, event: $event)';
return 'OfflineRecognizerResult(text: $text, tokens: $tokens, tokenLogProbs: $tokenLogProbs, timestamps: $timestamps, lang: $lang, emotion: $emotion, event: $event)';
}

Map<String, dynamic> toJson() => {
'text': text,
'tokens': tokens,
'token_log_probs': tokenLogProbs,
'timestamps': timestamps,
'lang': lang,
'emotion': emotion,
Expand All @@ -773,6 +779,7 @@ class OfflineRecognizerResult {

final String text;
final List<String> tokens;
final List<double> tokenLogProbs;
final List<double> timestamps;
final String lang;
final String emotion;
Expand All @@ -793,31 +800,32 @@ class OfflineRecognizer {
/// method of the returned instance to avoid memory leak.

factory OfflineRecognizer(OfflineRecognizerConfig config) {
final c = convertConfig(config);

if (SherpaOnnxBindings.createOfflineRecognizer == null) {
throw Exception("Please initialize sherpa-onnx first");
}

final ptr = SherpaOnnxBindings.createOfflineRecognizer?.call(c) ?? nullptr;
final c = convertConfig(config);

if (ptr == nullptr) {
throw Exception(
"Failed to create offline recognizer. Please check your config",
);
try {
final ptr = SherpaOnnxBindings.createOfflineRecognizer!.call(c);
if (ptr == nullptr) {
throw Exception(
"Failed to create offline recognizer. Please check your config",
);
}
return OfflineRecognizer._(ptr: ptr, config: config);
} finally {
freeConfig(c);
}

freeConfig(c);

return OfflineRecognizer._(ptr: ptr, config: config);
}

void setConfig(OfflineRecognizerConfig config) {
final c = convertConfig(config);

SherpaOnnxBindings.offlineRecognizerSetConfig?.call(ptr, c);

freeConfig(c);
try {
SherpaOnnxBindings.offlineRecognizerSetConfig?.call(ptr, c);
} finally {
freeConfig(c);
}
// we don't update this.config
}

Expand Down Expand Up @@ -1033,6 +1041,7 @@ class OfflineRecognizer {
return OfflineRecognizerResult(
text: '',
tokens: [],
tokenLogProbs: [],
timestamps: [],
lang: '',
emotion: '',
Expand All @@ -1044,13 +1053,8 @@ class OfflineRecognizer {

SherpaOnnxBindings.destroyOfflineStreamResultJson?.call(json);

return OfflineRecognizerResult(
text: parsedJson['text'],
tokens: List<String>.from(parsedJson['tokens']),
timestamps: List<double>.from(parsedJson['timestamps']),
lang: parsedJson['lang'],
emotion: parsedJson['emotion'],
event: parsedJson['event'],
return OfflineRecognizerResult.fromJson(
parsedJson as Map<String, dynamic>,
);
}

Expand Down
44 changes: 44 additions & 0 deletions flutter/sherpa_onnx/lib/src/offline_stream.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,49 @@ class OfflineStream {
calloc.free(p);
}

Map<String, List<double>>? getVocabLogProbs() {
final getFunc = SherpaOnnxBindings.getOfflineStreamVocabLogProbs;
final destroyFunc = SherpaOnnxBindings.destroyVocabLogProbs;

if (getFunc == null || destroyFunc == null) {
return null;
}

final vocabPtr = getFunc(ptr);
if (vocabPtr == nullptr) {
return null;
}

final vocabLogProbs = vocabPtr.ref;
final numTokens = vocabLogProbs.numTokens;
final vocabSize = vocabLogProbs.vocabSize;

// Defensive validation for native values
if (numTokens < 0 ||
vocabSize < 0 ||
numTokens > 10000 ||
vocabSize > 100000) {
destroyFunc(vocabPtr);
return null;
}

final Map<String, List<double>> result = {};

for (int tokenIdx = 0; tokenIdx < numTokens; tokenIdx++) {
final List<double> tokenProbs = [];

for (int vocabIdx = 0; vocabIdx < vocabSize; vocabIdx++) {
final index = tokenIdx * vocabSize + vocabIdx;
final logProb = vocabLogProbs.logProbs[index];
tokenProbs.add(logProb);
}

result['token_$tokenIdx'] = tokenProbs;
}

destroyFunc(vocabPtr);
return result;
}

Pointer<SherpaOnnxOfflineStream> ptr;
}
26 changes: 15 additions & 11 deletions flutter/sherpa_onnx/lib/src/online_recognizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -327,32 +327,37 @@ class OnlineRecognizerConfig {

class OnlineRecognizerResult {
OnlineRecognizerResult(
{required this.text, required this.tokens, required this.timestamps});
{required this.text, required this.tokens, required this.timestamps, this.ysProbs = const <double>[]});

factory OnlineRecognizerResult.fromJson(Map<String, dynamic> json) {
return OnlineRecognizerResult(
text: json['text'] as String,
tokens: List<String>.from(json['tokens'] as List),
timestamps: (json['timestamps'] as List)
.map<double>((e) => (e as num).toDouble())
.toList(),
text: json['text'] as String? ?? '',
tokens: (json['tokens'] as List?)?.cast<String>().toList() ?? const <String>[],
timestamps: (json['timestamps'] as List?)
?.map<double>((e) => (e as num).toDouble())
.toList() ?? const <double>[],
ysProbs: (json['ys_probs'] as List?)
?.map<double>((e) => (e as num).toDouble())
.toList() ?? const <double>[],
);
}

@override
String toString() {
return 'OnlineRecognizerResult(text: $text, tokens: $tokens, timestamps: $timestamps)';
return 'OnlineRecognizerResult(text: $text, tokens: $tokens, timestamps: $timestamps, ysProbs: $ysProbs)';
}

Map<String, dynamic> toJson() => {
'text': text,
'tokens': tokens,
'timestamps': timestamps,
'ys_probs': ysProbs,
};

final String text;
final List<String> tokens;
final List<double> timestamps;
final List<double> ysProbs;
}

class OnlineRecognizer {
Expand Down Expand Up @@ -496,10 +501,9 @@ class OnlineRecognizer {

SherpaOnnxBindings.destroyOnlineStreamResultJson?.call(json);

return OnlineRecognizerResult(
text: parsedJson['text'],
tokens: List<String>.from(parsedJson['tokens']),
timestamps: List<double>.from(parsedJson['timestamps']));
return OnlineRecognizerResult.fromJson(
parsedJson as Map<String, dynamic>,
);
}

void reset(OnlineStream stream) {
Expand Down
44 changes: 44 additions & 0 deletions flutter/sherpa_onnx/lib/src/online_stream.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,49 @@ class OnlineStream {
SherpaOnnxBindings.onlineStreamInputFinished?.call(ptr);
}

Map<String, List<double>>? getVocabLogProbs() {
final getFunc = SherpaOnnxBindings.getOnlineStreamVocabLogProbs;
final destroyFunc = SherpaOnnxBindings.destroyVocabLogProbs;

if (getFunc == null || destroyFunc == null) {
return null;
}

final vocabPtr = getFunc(this.ptr);
if (vocabPtr == nullptr) {
return null;
}

final vocabLogProbs = vocabPtr.ref;
final numTokens = vocabLogProbs.numTokens;
final vocabSize = vocabLogProbs.vocabSize;

// Defensive validation for native values
if (numTokens < 0 ||
vocabSize < 0 ||
numTokens > 10000 ||
vocabSize > 100000) {
destroyFunc(vocabPtr);
return null;
}

final Map<String, List<double>> result = {};

for (int tokenIdx = 0; tokenIdx < numTokens; tokenIdx++) {
final List<double> tokenProbs = [];

for (int vocabIdx = 0; vocabIdx < vocabSize; vocabIdx++) {
final index = tokenIdx * vocabSize + vocabIdx;
final logProb = vocabLogProbs.logProbs[index];
tokenProbs.add(logProb);
}

result['token_$tokenIdx'] = tokenProbs;
}

destroyFunc(vocabPtr);
return result;
}

Pointer<SherpaOnnxOnlineStream> ptr;
}
49 changes: 49 additions & 0 deletions flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,17 @@ final class SherpaOnnxSpokenLanguageIdentificationResult extends Struct {

final class SherpaOnnxSpokenLanguageIdentification extends Opaque {}

final class SherpaOnnxVocabLogProbs extends Struct {
// Flattened 2D array
external Pointer<Float> logProbs;

@Int32()
external int numTokens;

@Int32()
external int vocabSize;
}

final class SherpaOnnxOfflineSpeechDenoiser extends Opaque {}

typedef SherpaOnnxCreateOfflineSpeechDenoiserNative =
Expand Down Expand Up @@ -1724,6 +1735,20 @@ typedef SherpaOnnxGetGitSha1 = SherpaOnnxGetGitSha1Native;
typedef SherpaOnnxGetGitDateNative = Pointer<Utf8> Function();
typedef SherpaOnnxGetGitDate = SherpaOnnxGetGitDateNative;

typedef SherpaOnnxOnlineStreamGetVocabLogProbsNative
= Pointer<SherpaOnnxVocabLogProbs> Function(
Pointer<SherpaOnnxOnlineStream> stream);

typedef SherpaOnnxOfflineStreamGetVocabLogProbsNative
= Pointer<SherpaOnnxVocabLogProbs> Function(
Pointer<SherpaOnnxOfflineStream> stream);

typedef SherpaOnnxDestroyVocabLogProbsNative = Void Function(
Pointer<SherpaOnnxVocabLogProbs> logProbs);

typedef SherpaOnnxDestroyVocabLogProbsDart = void Function(
Pointer<SherpaOnnxVocabLogProbs>);

class SherpaOnnxBindings {
static SherpaOnnxCreateOfflineSpeechDenoiser?
sherpaOnnxCreateOfflineSpeechDenoiser;
Expand Down Expand Up @@ -1951,6 +1976,12 @@ class SherpaOnnxBindings {
static SherpaOnnxGetGitSha1? getGitSha1;
static SherpaOnnxGetGitDate? getGitDate;

static SherpaOnnxOnlineStreamGetVocabLogProbsNative?
getOnlineStreamVocabLogProbs;
static SherpaOnnxOfflineStreamGetVocabLogProbsNative?
getOfflineStreamVocabLogProbs;
static SherpaOnnxDestroyVocabLogProbsDart? destroyVocabLogProbs;

static void init(DynamicLibrary dynamicLibrary) {
sherpaOnnxCreateOfflineSpeechDenoiser ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxCreateOfflineSpeechDenoiserNative>>(
Expand Down Expand Up @@ -2674,5 +2705,23 @@ class SherpaOnnxBindings {
'SherpaOnnxGetGitDate',
)
.asFunction();

getOnlineStreamVocabLogProbs ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxOnlineStreamGetVocabLogProbsNative>>(
'SherpaOnnxOnlineStreamGetVocabLogProbs',
)
.asFunction();

getOfflineStreamVocabLogProbs ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxOfflineStreamGetVocabLogProbsNative>>(
'SherpaOnnxOfflineStreamGetVocabLogProbs',
)
.asFunction();

destroyVocabLogProbs ??= dynamicLibrary
.lookup<NativeFunction<SherpaOnnxDestroyVocabLogProbsNative>>(
'SherpaOnnxDestroyVocabLogProbs',
)
.asFunction();
}
}
Loading
Loading