Add JavaScript API for Cohere Transcribe. (#3458)

This pull request introduces support for the Cohere Transcribe model across multiple platforms, including Node.js addons, standard Node.js, and WebAssembly. Key changes include adding C++ configuration logic, implementing a setOption method for offline streams to handle language selection, and providing new example scripts for both synchronous and asynchronous transcription.
This commit is contained in:
Fangjun Kuang authored and GitHub committed 2026-04-02 20:44:45 +08:00
1 parent 6864344d4b
commit d4465bcbdf
12 files changed
+404 -14

No files matched your search

+10
View File
@@ -10,6 +10,16 @@ arch=$(node -p "require('os').arch()")
platform=$(node -p "require('os').platform()")
node_version=$(node -p "process.versions.node.split('.')[0]")
echo "----------Cohere Transcribe----------"
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
tar xvf sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
rm sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
node ./test_asr_non_streaming_cohere_transcribe.js
node ./test_asr_non_streaming_cohere_transcribe_async.js
rm -rf sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01
if [[ "$SKIP_QWEN3" != "true" ]]; then
echo "----------Qwen3 ASR----------"
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-qwen3-asr-0.6B-int8-2026-03-25.tar.bz2
+1
View File
@@ -4,6 +4,7 @@ on:
push:
branches:
- master
- nodejs-api
paths:
- '.github/workflows/test-nodejs.yaml'
- 'build-wasm-simd-nodejs.sh'
@@ -179,6 +179,28 @@ static SherpaOnnxOfflineQwen3ASRModelConfig GetOfflineQwen3AsrModelConfig(
return c;
}
static SherpaOnnxOfflineCohereTranscribeModelConfig
GetOfflineCohereTranscribeModelConfig(Napi::Object obj) {
SherpaOnnxOfflineCohereTranscribeModelConfig c;
memset(&c, 0, sizeof(c));
c.use_punct = 1;
c.use_itn = 1;
if (!obj.Has("cohereTranscribe") || !obj.Get("cohereTranscribe").IsObject()) {
return c;
}
Napi::Object o = obj.Get("cohereTranscribe").As<Napi::Object>();
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
SHERPA_ONNX_ASSIGN_ATTR_STR(decoder, decoder);
SHERPA_ONNX_ASSIGN_ATTR_STR(language, language);
SHERPA_ONNX_ASSIGN_ATTR_INT32(use_punct, usePunct);
SHERPA_ONNX_ASSIGN_ATTR_INT32(use_itn, useItn);
return c;
}
static SherpaOnnxOfflineDolphinModelConfig GetOfflineDolphinModelConfig(
Napi::Object obj) {
SherpaOnnxOfflineDolphinModelConfig c;
@@ -353,6 +375,7 @@ static SherpaOnnxOfflineModelConfig GetOfflineModelConfig(Napi::Object obj) {
c.funasr_nano = GetOfflineFunAsrNanoModelConfig(o);
c.fire_red_asr_ctc = GetOfflineFireRedAsrCtcModelConfig(o);
c.qwen3_asr = GetOfflineQwen3AsrModelConfig(o);
c.cohere_transcribe = GetOfflineCohereTranscribeModelConfig(o);
SHERPA_ONNX_ASSIGN_ATTR_STR(tokens, tokens);
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
@@ -465,6 +488,10 @@ static void FreeConfig(const SherpaOnnxOfflineRecognizerConfig &c) {
SHERPA_ONNX_DELETE_C_STR(c.model_config.qwen3_asr.tokenizer);
SHERPA_ONNX_DELETE_C_STR(c.model_config.qwen3_asr.hotwords);
SHERPA_ONNX_DELETE_C_STR(c.model_config.cohere_transcribe.encoder);
SHERPA_ONNX_DELETE_C_STR(c.model_config.cohere_transcribe.decoder);
SHERPA_ONNX_DELETE_C_STR(c.model_config.cohere_transcribe.language);
SHERPA_ONNX_DELETE_C_STR(c.model_config.fire_red_asr_ctc.model);
SHERPA_ONNX_DELETE_C_STR(c.model_config.tokens);
@@ -727,6 +754,36 @@ static void AcceptWaveformOfflineWrapper(const Napi::CallbackInfo &info) {
#endif
}
static void OfflineStreamSetOptionWrapper(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
if (info.Length() != 3) {
std::ostringstream os;
os << "Expect 3 arguments. Given: " << info.Length();
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
return;
}
if (!info[0].IsExternal()) {
Napi::TypeError::New(env, "Argument 0 should be an offline stream pointer.")
.ThrowAsJavaScriptException();
return;
}
if (!info[1].IsString() || !info[2].IsString()) {
Napi::TypeError::New(env, "Arguments 1 and 2 should be strings.")
.ThrowAsJavaScriptException();
return;
}
const SherpaOnnxOfflineStream *stream =
info[0].As<Napi::External<SherpaOnnxOfflineStream>>().Data();
std::string key = info[1].As<Napi::String>().Utf8Value();
std::string value = info[2].As<Napi::String>().Utf8Value();
SherpaOnnxOfflineStreamSetOption(stream, key.c_str(), value.c_str());
}
static void OfflineRecognizerSetConfigWrapper(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
if (info.Length() != 2) {
@@ -911,6 +968,9 @@ void InitNonStreamingAsr(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "acceptWaveformOffline"),
Napi::Function::New(env, AcceptWaveformOfflineWrapper));
exports.Set(Napi::String::New(env, "offlineStreamSetOption"),
Napi::Function::New(env, OfflineStreamSetOptionWrapper));
exports.Set(Napi::String::New(env, "decodeOfflineStream"),
Napi::Function::New(env, DecodeOfflineStreamWrapper));
+23 -1
View File
@@ -75,7 +75,7 @@ The following tables list the examples in this folder.
|File| Description|
|---|---|
|[ ./test_speaker_identification.js]( ./test_speaker_identification.js)| Speaker identification from a file|
|[./test_speaker_identification.js](./test_speaker_identification.js)| Speaker identification from a file|
## Spoken language identification
@@ -139,6 +139,8 @@ The following tables list the examples in this folder.
|[./test_asr_non_streaming_medasr_ctc.js](./test_asr_non_streaming_medasr_ctc.js)|Non-streaming speech recognition from a file using a [Google MedASR](https://github.com/google-health/medasr) CTC model with greedy search|
|[./test_asr_non_streaming_funasr_nano.js](./test_asr_non_streaming_funasr_nano.js)|Non-streaming speech recognition from a file using a [FunASR Nano](https://modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512) model|
|[./test_asr_non_streaming_funasr_nano_async.js](./test_asr_non_streaming_funasr_nano_async.js)|Async non-streaming speech recognition from multiple files using a [FunASR Nano](https://modelscope.cn/models/FunAudioLLM/Fun-ASR-Nano-2512) model|
|[./test_asr_non_streaming_cohere_transcribe.js](./test_asr_non_streaming_cohere_transcribe.js)|Non-streaming speech recognition from a file using a [Cohere Transcribe](https://cohere.com/research/papers/cohere-labs-aya-expanse-open-weights-and-multilingual-api-2025) model|
|[./test_asr_non_streaming_cohere_transcribe_async.js](./test_asr_non_streaming_cohere_transcribe_async.js)|Async non-streaming speech recognition from multiple files using a Cohere Transcribe model|
|[./test_asr_non_streaming_qwen3_asr.js](./test_asr_non_streaming_qwen3_asr.js)|Non-streaming speech recognition from a file using a [Qwen3 ASR](https://github.com/QwenLM/Qwen3-ASR) model|
|[./test_asr_non_streaming_qwen3_asr_async.js](./test_asr_non_streaming_qwen3_asr_async.js)|Async non-streaming speech recognition from multiple files using a [Qwen3 ASR](https://github.com/QwenLM/Qwen3-ASR) model|
|[./test_asr_non_streaming_nemo_canary.js](./test_asr_non_streaming_nemo_canary.js)|Non-streaming speech recognition from a file using a [NeMo](https://github.com/NVIDIA/NeMo) [Canary](https://k2-fsa.github.io/sherpa/onnx/nemo/canary.html#sherpa-onnx-nemo-canary-180m-flash-en-es-de-fr-int8-english-spanish-german-french) model|
@@ -493,6 +495,26 @@ rm sherpa-onnx-funasr-nano-int8-2025-12-30.tar.bz2
node ./test_asr_non_streaming_funasr_nano.js
```
### Asynchronous non-streaming speech recognition with Cohere Transcribe models
```bash
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
tar xvf sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
rm sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
node ./test_asr_non_streaming_cohere_transcribe_async.js
```
### Non-streaming speech recognition with Cohere Transcribe models
```bash
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
tar xvf sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
rm sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
node ./test_asr_non_streaming_cohere_transcribe.js
```
### Asynchronous non-streaming speech recognition with Qwen3 ASR models
```bash
@@ -0,0 +1,37 @@
// Copyright (c) 2026 Xiaomi Corporation
const sherpa_onnx = require('sherpa-onnx-node');
const config = {
'featConfig': {
'sampleRate': 16000,
'featureDim': 80,
},
'modelConfig': {
'cohereTranscribe': {
'encoder':
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/encoder.int8.onnx',
'decoder':
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/decoder.int8.onnx',
'usePunct': 1,
'useItn': 1,
},
'tokens':
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/tokens.txt',
'numThreads': 2,
'provider': 'cpu',
'debug': 0,
}
};
const waveFilename =
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/test_wavs/en.wav';
const recognizer = new sherpa_onnx.OfflineRecognizer(config);
const stream = recognizer.createStream();
stream.setOption('language', 'en');
const wave = sherpa_onnx.readWave(waveFilename);
stream.acceptWaveform({sampleRate: wave.sampleRate, samples: wave.samples});
recognizer.decode(stream);
const result = recognizer.getResult(stream);
console.log('result\n', result);
@@ -0,0 +1,99 @@
// Copyright (c) 2026 Xiaomi Corporation
// This file shows how to use the async API to decode multiple files
const path = require('path');
const sherpa_onnx = require('sherpa-onnx-node');
/**
* Create an OfflineRecognizer with Cohere Transcribe asynchronously.
*/
async function createRecognizerAsync(modelDir, numThreads = 2, debug = 0) {
const config = {
featConfig: {
sampleRate: 16000,
featureDim: 80,
},
modelConfig: {
cohereTranscribe: {
encoder: path.join(modelDir, 'encoder.int8.onnx'),
decoder: path.join(modelDir, 'decoder.int8.onnx'),
usePunct: 1,
useItn: 1,
},
tokens: path.join(modelDir, 'tokens.txt'),
numThreads,
provider: 'cpu',
debug,
},
};
return await sherpa_onnx.OfflineRecognizer.createAsync(config);
}
/**
* Read a waveform and create a stream for decoding.
*/
function createStreamFromFile(recognizer, file, language) {
const wave = sherpa_onnx.readWave(file);
const stream = recognizer.createStream();
stream.setOption('language', language);
stream.acceptWaveform({sampleRate: wave.sampleRate, samples: wave.samples});
return stream;
}
async function main() {
const modelDir = './sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01';
const recognizer = await createRecognizerAsync(modelDir);
const testFiles = [
{
language: 'en',
file: path.join(modelDir, 'test_wavs/en.wav'),
},
{
language: 'fr',
file: path.join(modelDir, 'test_wavs/fr.wav'),
},
{
language: 'zh',
file: path.join(modelDir, 'test_wavs/zh.wav'),
},
{
language: 'de',
file: path.join(modelDir, 'test_wavs/de.wav'),
},
{
language: 'es',
file: path.join(modelDir, 'test_wavs/es.wav'),
},
{
language: 'ja',
file: path.join(modelDir, 'test_wavs/ja.wav'),
},
{
language: 'ko',
file: path.join(modelDir, 'test_wavs/ko.wav'),
},
{
language: 'vi',
file: path.join(modelDir, 'test_wavs/vi.wav'),
},
{
language: 'ar',
file: path.join(modelDir, 'test_wavs/ar.wav'),
},
];
const streams = testFiles.map(
entry => createStreamFromFile(recognizer, entry.file, entry.language));
const results =
await Promise.all(streams.map(stream => recognizer.decodeAsync(stream)));
console.log('Concurrent decode results:');
testFiles.forEach((entry, i) => {
console.log(`${entry.language} ${entry.file}: ${results[i].text}`);
});
}
main().catch(console.error);
+17
View File
@@ -303,6 +303,23 @@ rm sherpa-onnx-funasr-nano-int8-2025-12-30.tar.bz2
node ./test-offline-funasr-nano.js
```
## ./test-offline-cohere-transcribe.js
[./test-offline-cohere-transcribe.js](./test-offline-cohere-transcribe.js)
demonstrates how to decode a file with a Cohere Transcribe model. In the code
we use
[sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2).
You can use the following command to run it:
```bash
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
tar xvf sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
rm sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
node ./test-offline-cohere-transcribe.js
```
## ./test-offline-qwen3-asr.js
[./test-offline-qwen3-asr.js](./test-offline-qwen3-asr.js) demonstrates
@@ -0,0 +1,38 @@
// Copyright (c) 2026 Xiaomi Corporation (authors: Fangjun Kuang)
//
const sherpa_onnx = require('sherpa-onnx');
function createOfflineRecognizer() {
const config = {
modelConfig: {
cohereTranscribe: {
encoder:
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/encoder.int8.onnx',
decoder:
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/decoder.int8.onnx',
usePunct: 1,
useItn: 1,
},
tokens:
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/tokens.txt',
}
};
return sherpa_onnx.createOfflineRecognizer(config);
}
const recognizer = createOfflineRecognizer();
const stream = recognizer.createStream();
stream.setOption('language', 'en');
const waveFilename =
'./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/test_wavs/en.wav';
const wave = sherpa_onnx.readWave(waveFilename);
stream.acceptWaveform(wave.sampleRate, wave.samples);
recognizer.decode(stream);
const text = recognizer.getResult(stream).text;
console.log(text);
stream.free();
recognizer.free();
@@ -33,6 +33,15 @@ class OfflineStream {
acceptWaveform(obj) {
addon.acceptWaveformOffline(this.handle, obj);
}
/**
* Set a string option on the underlying offline stream.
* @param {string} key
* @param {string} value
*/
setOption(key, value) {
addon.offlineStreamSetOption(this.handle, key, value);
}
}
/**
+21 -10
View File
@@ -234,9 +234,19 @@
* @property {number} [useInverseTextNormalization]
*/
/**
* Offline model config.
* @typedef {Object} OfflineModelConfig
/**
* Offline Cohere Transcribe model config
* @typedef {Object} OfflineCohereTranscribeModelConfig
* @property {string} [encoder]
* @property {string} [decoder]
* @property {string} [language]
* @property {number} [usePunct]
* @property {number} [useItn]
*/
/**
* Offline model config.
* @typedef {Object} OfflineModelConfig
* @property {OfflineTransducerModelConfig} [transducer]
* @property {OfflineParaformerModelConfig} [paraformer]
* @property {OfflineZipformerCtcModelConfig} [zipformerCtc]
@@ -245,13 +255,14 @@
* @property {OfflineMedAsrCtcModelConfig} [medasr]
* @property {OfflineDolphinModelConfig} [dolphin]
* @property {OfflineNeMoCtcModelConfig} [nemoCtc]
* @property {OfflineCanaryModelConfig} [canary]
* @property {OfflineWhisperModelConfig} [whisper]
* @property {OfflineFireRedAsrModelConfig} [fireRedAsr]
* @property {OfflineMoonshineModelConfig} [moonshine]
* @property {OfflineTdnnModelConfig} [tdnn]
* @property {OfflineSenseVoiceModelConfig} [senseVoice]
* @property {string} [tokens]
* @property {OfflineCanaryModelConfig} [canary]
* @property {OfflineWhisperModelConfig} [whisper]
* @property {OfflineFireRedAsrModelConfig} [fireRedAsr]
* @property {OfflineMoonshineModelConfig} [moonshine]
* @property {OfflineTdnnModelConfig} [tdnn]
* @property {OfflineSenseVoiceModelConfig} [senseVoice]
* @property {OfflineCohereTranscribeModelConfig} [cohereTranscribe]
* @property {string} [tokens]
* @property {number} [numThreads]
* @property {boolean|number} [debug]
* @property {string} [provider]
+64 -2
View File
@@ -71,6 +71,10 @@ function freeConfig(config, Module) {
freeConfig(config.qwen3Asr, Module)
}
if ('cohereTranscribe' in config) {
freeConfig(config.cohereTranscribe, Module)
}
if ('funasrNano' in config) {
freeConfig(config.funasrNano, Module)
}
@@ -1215,6 +1219,47 @@ function initSherpaOnnxOfflineTdnnModelConfig(config, Module) {
};
}
function initSherpaOnnxOfflineCohereTranscribeModelConfig(config, Module) {
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
const languageLen = Module.lengthBytesUTF8(config.language || '') + 1;
const n = encoderLen + decoderLen + languageLen;
const buffer = Module._malloc(n);
const len = 5 * 4; // 3 pointers + 2 ints
const ptr = Module._malloc(len);
let offset = 0;
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
offset += encoderLen;
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
offset += decoderLen;
Module.stringToUTF8(config.language || '', buffer + offset, languageLen);
offset += languageLen;
offset = 0;
Module.setValue(ptr, buffer + offset, 'i8*');
offset += encoderLen;
Module.setValue(ptr + 4, buffer + offset, 'i8*');
offset += decoderLen;
Module.setValue(ptr + 8, buffer + offset, 'i8*');
offset += languageLen;
Module.setValue(ptr + 12, config.usePunct ?? 1, 'i32');
Module.setValue(ptr + 16, config.useItn ?? 1, 'i32');
return {
buffer: buffer,
ptr: ptr,
len: len,
};
}
function initSherpaOnnxOfflineSenseVoiceModelConfig(config, Module) {
const modelLen = Module.lengthBytesUTF8(config.model || '') + 1;
const languageLen = Module.lengthBytesUTF8(config.language || '') + 1;
@@ -1339,6 +1384,16 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
};
}
if (!('cohereTranscribe' in config)) {
config.cohereTranscribe = {
encoder: '',
decoder: '',
language: '',
usePunct: 1,
useItn: 1,
};
}
if (!('funasrNano' in config)) {
config.funasrNano = {
encoderAdaptor: '',
@@ -1459,11 +1514,14 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
const qwen3Asr =
initSherpaOnnxOfflineQwen3AsrModelConfig(config.qwen3Asr, Module);
const cohereTranscribe = initSherpaOnnxOfflineCohereTranscribeModelConfig(
config.cohereTranscribe, Module);
const len = transducer.len + paraformer.len + nemoCtc.len + whisper.len +
tdnn.len + 8 * 4 + senseVoice.len + moonshine.len + fireRedAsr.len +
dolphin.len + zipformerCtc.len + canary.len + wenetCtc.len +
omnilingual.len + medasr.len + funasrNano.len + fireRedAsrCtc.len +
qwen3Asr.len;
qwen3Asr.len + cohereTranscribe.len;
const ptr = Module._malloc(len);
@@ -1589,6 +1647,9 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
Module._CopyHeap(qwen3Asr.ptr, qwen3Asr.len, ptr + offset);
offset += qwen3Asr.len;
Module._CopyHeap(cohereTranscribe.ptr, cohereTranscribe.len, ptr + offset);
offset += cohereTranscribe.len;
return {
buffer: buffer,
ptr: ptr,
@@ -1609,7 +1670,8 @@ function initSherpaOnnxOfflineModelConfig(config, Module) {
medasr: medasr,
funasrNano: funasrNano,
fireRedAsrCtc: fireRedAsrCtc,
qwen3Asr: qwen3Asr
qwen3Asr: qwen3Asr,
cohereTranscribe: cohereTranscribe
};
}
+25 -1
View File
@@ -20,6 +20,8 @@ static_assert(sizeof(SherpaOnnxOfflineMedAsrCtcModelConfig) == 4, "");
static_assert(sizeof(SherpaOnnxOfflineFireRedAsrCtcModelConfig) == 4, "");
static_assert(sizeof(SherpaOnnxOfflineFunASRNanoModelConfig) == 13 * 4, "");
static_assert(sizeof(SherpaOnnxOfflineQwen3ASRModelConfig) == 10 * 4, "");
static_assert(sizeof(SherpaOnnxOfflineCohereTranscribeModelConfig) == 5 * 4,
"");
static_assert(sizeof(SherpaOnnxOfflineDolphinModelConfig) == 4, "");
static_assert(sizeof(SherpaOnnxOfflineNemoEncDecCtcModelConfig) == 4, "");
static_assert(sizeof(SherpaOnnxOfflineWhisperModelConfig) == 7 * 4, "");
@@ -47,7 +49,8 @@ static_assert(sizeof(SherpaOnnxOfflineModelConfig) ==
sizeof(SherpaOnnxOfflineMedAsrCtcModelConfig) +
sizeof(SherpaOnnxOfflineFunASRNanoModelConfig) +
sizeof(SherpaOnnxOfflineFireRedAsrCtcModelConfig) +
sizeof(SherpaOnnxOfflineQwen3ASRModelConfig),
sizeof(SherpaOnnxOfflineQwen3ASRModelConfig) +
sizeof(SherpaOnnxOfflineCohereTranscribeModelConfig),
"");
static_assert(sizeof(SherpaOnnxFeatureConfig) == 2 * 4, "");
@@ -168,6 +171,8 @@ void PrintOfflineRecognizerConfig(SherpaOnnxOfflineRecognizerConfig *config) {
auto medasr = &model_config->medasr;
auto funasr_nano = &model_config->funasr_nano;
auto fire_red_asr_ctc = &model_config->fire_red_asr_ctc;
auto qwen3_asr = &model_config->qwen3_asr;
auto cohere_transcribe = &model_config->cohere_transcribe;
fprintf(stdout, "----------offline transducer model config----------\n");
fprintf(stdout, "encoder: %s\n", transducer->encoder);
@@ -243,6 +248,25 @@ void PrintOfflineRecognizerConfig(SherpaOnnxOfflineRecognizerConfig *config) {
fprintf(stdout, "----------offline FireRedASR CTC model config----------\n");
fprintf(stdout, "model: %s\n", fire_red_asr_ctc->model);
fprintf(stdout, "----------offline Qwen3 ASR model config----------\n");
fprintf(stdout, "conv_frontend: %s\n", qwen3_asr->conv_frontend);
fprintf(stdout, "encoder: %s\n", qwen3_asr->encoder);
fprintf(stdout, "decoder: %s\n", qwen3_asr->decoder);
fprintf(stdout, "tokenizer: %s\n", qwen3_asr->tokenizer);
fprintf(stdout, "max_total_len: %d\n", qwen3_asr->max_total_len);
fprintf(stdout, "max_new_tokens: %d\n", qwen3_asr->max_new_tokens);
fprintf(stdout, "temperature: %f\n", qwen3_asr->temperature);
fprintf(stdout, "top_p: %f\n", qwen3_asr->top_p);
fprintf(stdout, "seed: %d\n", qwen3_asr->seed);
fprintf(stdout, "hotwords: %s\n", qwen3_asr->hotwords);
fprintf(stdout, "----------offline Cohere Transcribe model config----------\n");
fprintf(stdout, "encoder: %s\n", cohere_transcribe->encoder);
fprintf(stdout, "decoder: %s\n", cohere_transcribe->decoder);
fprintf(stdout, "language: %s\n", cohere_transcribe->language);
fprintf(stdout, "use_punct: %d\n", cohere_transcribe->use_punct);
fprintf(stdout, "use_itn: %d\n", cohere_transcribe->use_itn);
fprintf(stdout, "tokens: %s\n", model_config->tokens);
fprintf(stdout, "num_threads: %d\n", model_config->num_threads);
fprintf(stdout, "provider: %s\n", model_config->provider);