Skip to content

Commit 3cd0598

Browse files
authored
C api example for sense voice (k2-fsa#1165)
1 parent 27ac315 commit 3cd0598

File tree

4 files changed

+248
-9
lines changed

4 files changed

+248
-9
lines changed

.github/workflows/c-api.yaml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
name: c-api
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
tags:
8+
- 'v[0-9]+.[0-9]+.[0-9]+*'
9+
paths:
10+
- '.github/workflows/c-api.yaml'
11+
- 'CMakeLists.txt'
12+
- 'cmake/**'
13+
- 'sherpa-onnx/csrc/*'
14+
- 'sherpa-onnx/c-api/*'
15+
- 'c-api-examples/**'
16+
pull_request:
17+
branches:
18+
- master
19+
paths:
20+
- '.github/workflows/c-api.yaml'
21+
- 'CMakeLists.txt'
22+
- 'cmake/**'
23+
- 'sherpa-onnx/csrc/*'
24+
- 'sherpa-onnx/c-api/*'
25+
- 'c-api-examples/**'
26+
27+
workflow_dispatch:
28+
29+
concurrency:
30+
group: c-api-${{ github.ref }}
31+
cancel-in-progress: true
32+
33+
jobs:
34+
c_api:
35+
name: ${{ matrix.os }}
36+
runs-on: ${{ matrix.os }}
37+
strategy:
38+
fail-fast: false
39+
matrix:
40+
os: [ubuntu-latest, macos-latest]
41+
42+
steps:
43+
- uses: actions/checkout@v4
44+
with:
45+
fetch-depth: 0
46+
47+
- name: ccache
48+
uses: hendrikmuhs/[email protected]
49+
with:
50+
key: ${{ matrix.os }}-c-api-shared
51+
52+
- name: Build sherpa-onnx
53+
shell: bash
54+
run: |
55+
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
56+
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
57+
cmake --version
58+
59+
mkdir build
60+
cd build
61+
62+
cmake \
63+
-D CMAKE_BUILD_TYPE=Release \
64+
-D BUILD_SHARED_LIBS=ON \
65+
-D CMAKE_INSTALL_PREFIX=./install \
66+
-D SHERPA_ONNX_ENABLE_BINARY=OFF \
67+
..
68+
69+
make -j2 install
70+
71+
ls -lh install/lib
72+
ls -lh install/include
73+
74+
if [[ ${{ matrix.os }} == ubuntu-latest ]]; then
75+
ldd ./install/lib/libsherpa-onnx-c-api.so
76+
echo "---"
77+
readelf -d ./install/lib/libsherpa-onnx-c-api.so
78+
fi
79+
80+
if [[ ${{ matrix.os }} == macos-latest ]]; then
81+
otool -L ./install/lib/libsherpa-onnx-c-api.dylib
82+
fi
83+
84+
- name: Test sense-voice
85+
shell: bash
86+
run: |
87+
gcc -o sense-voice-c-api ./c-api-examples/sense-voice-c-api.c \
88+
-I ./build/install/include \
89+
-L ./build/install/lib/ \
90+
-l sherpa-onnx-c-api \
91+
-l onnxruntime
92+
93+
ls -lh sense-voice-c-api
94+
95+
if [[ ${{ matrix.os }} == ubuntu-latest ]]; then
96+
ldd ./sense-voice-c-api
97+
echo "----"
98+
readelf -d ./sense-voice-c-api
99+
fi
100+
101+
# Now download models
102+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
103+
tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
104+
rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
105+
106+
ls -lh sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17
107+
echo "---"
108+
ls -lh sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/test_wavs
109+
110+
export LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH
111+
export DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH
112+
113+
./sense-voice-c-api
114+
115+
rm -rf sherpa-onnx-sense-voice-*
116+
117+
- name: Test whisper
118+
shell: bash
119+
run: |
120+
gcc -o whisper-c-api ./c-api-examples/whisper-c-api.c \
121+
-I ./build/install/include \
122+
-L ./build/install/lib/ \
123+
-l sherpa-onnx-c-api \
124+
-l onnxruntime
125+
126+
ls -lh whisper-c-api
127+
128+
if [[ ${{ matrix.os }} == ubuntu-latest ]]; then
129+
ldd ./whisper-c-api
130+
echo "----"
131+
readelf -d ./whisper-c-api
132+
fi
133+
134+
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-whisper-tiny.tar.bz2
135+
tar xvf sherpa-onnx-whisper-tiny.tar.bz2
136+
rm sherpa-onnx-whisper-tiny.tar.bz2
137+
138+
ls -lh sherpa-onnx-whisper-tiny
139+
echo "---"
140+
ls -lh sherpa-onnx-whisper-tiny/test_wavs
141+
142+
export LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH
143+
export DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH
144+
145+
./whisper-c-api
146+
147+
rm -rf sherpa-onnx-whisper-*

c-api-examples/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ target_link_libraries(audio-tagging-c-api sherpa-onnx-c-api)
2424
add_executable(add-punctuation-c-api add-punctuation-c-api.c)
2525
target_link_libraries(add-punctuation-c-api sherpa-onnx-c-api)
2626

27-
add_executable(offline-stt-c-api offline-stt-c-api.c)
28-
target_link_libraries(offline-stt-c-api sherpa-onnx-c-api)
27+
add_executable(whisper-c-api whisper-c-api.c)
28+
target_link_libraries(whisper-c-api sherpa-onnx-c-api)
29+
30+
add_executable(sense-voice-c-api sense-voice-c-api.c)
31+
target_link_libraries(sense-voice-c-api sherpa-onnx-c-api)
2932

3033
if(SHERPA_ONNX_HAS_ALSA)
3134
add_subdirectory(./asr-microphone-example)

c-api-examples/sense-voice-c-api.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// c-api-examples/sense-voice-c-api.c
2+
//
3+
// Copyright (c) 2024 Xiaomi Corporation
4+
5+
//
6+
// This file demonstrates how to use SenseVoice with sherpa-onnx's C API.
7+
// clang-format off
8+
//
9+
// wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
10+
// tar xvf sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
11+
// rm sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17.tar.bz2
12+
//
13+
// clang-format on
14+
15+
#include <stdio.h>
16+
#include <stdlib.h>
17+
#include <string.h>
18+
19+
#include "sherpa-onnx/c-api/c-api.h"
20+
21+
int32_t main() {
22+
// You can find more test waves from
23+
// https://hf-mirror.com/spaces/k2-fsa/spoken-language-identification/tree/main/test_wavs
24+
const char *wav_filename =
25+
"./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/test_wavs/en.wav";
26+
const char *model_filename =
27+
"./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/model.int8.onnx";
28+
const char *tokens_filename =
29+
"./sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17/tokens.txt";
30+
const char *language = "auto";
31+
const char *provider = "cpu";
32+
int32_t use_inverse_text_normalization = 1;
33+
34+
const SherpaOnnxWave *wave = SherpaOnnxReadWave(wav_filename);
35+
if (wave == NULL) {
36+
fprintf(stderr, "Failed to read %s\n", wav_filename);
37+
return -1;
38+
}
39+
40+
SherpaOnnxOfflineSenseVoiceModelConfig sense_voice_config;
41+
memset(&sense_voice_config, 0, sizeof(sense_voice_config));
42+
sense_voice_config.model = model_filename;
43+
sense_voice_config.language = language;
44+
sense_voice_config.use_itn = use_inverse_text_normalization;
45+
46+
// Offline model config
47+
SherpaOnnxOfflineModelConfig offline_model_config;
48+
memset(&offline_model_config, 0, sizeof(offline_model_config));
49+
offline_model_config.debug = 1;
50+
offline_model_config.num_threads = 1;
51+
offline_model_config.provider = provider;
52+
offline_model_config.tokens = tokens_filename;
53+
offline_model_config.sense_voice = sense_voice_config;
54+
55+
// Recognizer config
56+
SherpaOnnxOfflineRecognizerConfig recognizer_config;
57+
memset(&recognizer_config, 0, sizeof(recognizer_config));
58+
recognizer_config.decoding_method = "greedy_search";
59+
recognizer_config.model_config = offline_model_config;
60+
61+
SherpaOnnxOfflineRecognizer *recognizer =
62+
CreateOfflineRecognizer(&recognizer_config);
63+
64+
if (recognizer == NULL) {
65+
fprintf(stderr, "Please check your config!\n");
66+
SherpaOnnxFreeWave(wave);
67+
return -1;
68+
}
69+
70+
SherpaOnnxOfflineStream *stream = CreateOfflineStream(recognizer);
71+
72+
AcceptWaveformOffline(stream, wave->sample_rate, wave->samples,
73+
wave->num_samples);
74+
DecodeOfflineStream(recognizer, stream);
75+
const SherpaOnnxOfflineRecognizerResult *result =
76+
GetOfflineStreamResult(stream);
77+
78+
fprintf(stderr, "Decoded text: %s\n", result->text);
79+
80+
DestroyOfflineRecognizerResult(result);
81+
DestroyOfflineStream(stream);
82+
DestroyOfflineRecognizer(recognizer);
83+
SherpaOnnxFreeWave(wave);
84+
85+
return 0;
86+
}

c-api-examples/offline-stt-c-api.c renamed to c-api-examples/whisper-c-api.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
#include "sherpa-onnx/c-api/c-api.h"
2222

2323
int32_t main() {
24-
// You can find more test waves from
25-
// https://hf-mirror.com/spaces/k2-fsa/spoken-language-identification/tree/main/test_wavs
2624
const char *wav_filename = "./sherpa-onnx-whisper-tiny/test_wavs/0.wav";
2725
const char *encoder_filename = "sherpa-onnx-whisper-tiny/tiny-encoder.onnx";
2826
const char *decoder_filename = "sherpa-onnx-whisper-tiny/tiny-decoder.onnx";
@@ -48,31 +46,36 @@ int32_t main() {
4846
// Offline model config
4947
SherpaOnnxOfflineModelConfig offline_model_config;
5048
memset(&offline_model_config, 0, sizeof(offline_model_config));
51-
offline_model_config.bpe_vocab = "";
5249
offline_model_config.debug = 1;
5350
offline_model_config.num_threads = 1;
5451
offline_model_config.provider = provider;
5552
offline_model_config.tokens = tokens_filename;
5653
offline_model_config.whisper = whisper_config;
57-
offline_model_config.sense_voice =
58-
(SherpaOnnxOfflineSenseVoiceModelConfig){"", "", 0};
5954

6055
// Recognizer config
6156
SherpaOnnxOfflineRecognizerConfig recognizer_config;
6257
memset(&recognizer_config, 0, sizeof(recognizer_config));
6358
recognizer_config.decoding_method = "greedy_search";
64-
recognizer_config.feat_config = (SherpaOnnxFeatureConfig){16000, 512};
6559
recognizer_config.model_config = offline_model_config;
6660

6761
SherpaOnnxOfflineRecognizer *recognizer =
6862
CreateOfflineRecognizer(&recognizer_config);
6963

64+
if (recognizer == NULL) {
65+
fprintf(stderr, "Please check your config!\n");
66+
67+
SherpaOnnxFreeWave(wave);
68+
69+
return -1;
70+
}
71+
7072
SherpaOnnxOfflineStream *stream = CreateOfflineStream(recognizer);
7173

7274
AcceptWaveformOffline(stream, wave->sample_rate, wave->samples,
7375
wave->num_samples);
7476
DecodeOfflineStream(recognizer, stream);
75-
SherpaOnnxOfflineRecognizerResult *result = GetOfflineStreamResult(stream);
77+
const SherpaOnnxOfflineRecognizerResult *result =
78+
GetOfflineStreamResult(stream);
7679

7780
fprintf(stderr, "Decoded text: %s\n", result->text);
7881

0 commit comments

Comments
 (0)