From e9dbeeedc334eb2b09679e4c49d270d89992a5a9 Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Mon, 29 Dec 2025 11:29:54 +0800 Subject: [PATCH 1/2] Add Go API for Google MedAsr model --- .github/workflows/test-go.yaml | 14 +++ .../go.mod | 3 + .../main.go | 97 +++++++++++++++++++ .../run.sh | 15 +++ .../.gitignore | 1 + .../go.mod | 15 +++ .../main.go | 1 + .../run.sh | 1 + scripts/go/sherpa_onnx.go | 11 +++ 9 files changed, 158 insertions(+) create mode 100644 go-api-examples/non-streaming-medasr-ctc-decode-files/go.mod create mode 100644 go-api-examples/non-streaming-medasr-ctc-decode-files/main.go create mode 100755 go-api-examples/non-streaming-medasr-ctc-decode-files/run.sh create mode 100644 scripts/go/_internal/non-streaming-medasr-ctc-decode-files/.gitignore create mode 100644 scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod create mode 120000 scripts/go/_internal/non-streaming-medasr-ctc-decode-files/main.go create mode 120000 scripts/go/_internal/non-streaming-medasr-ctc-decode-files/run.sh diff --git a/.github/workflows/test-go.yaml b/.github/workflows/test-go.yaml index 53faad2def..8bb715df30 100644 --- a/.github/workflows/test-go.yaml +++ b/.github/workflows/test-go.yaml @@ -102,6 +102,7 @@ jobs: cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/non-streaming-canary-decode-files/ cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/non-streaming-decode-files/ cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/non-streaming-omnilingual-asr-ctc-decode-files + cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/non-streaming-medasr-ctc-decode-files cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/non-streaming-speaker-diarization/ cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/non-streaming-tts/ cp -v ../scripts/go/_internal/lib/x86_64-pc-windows-gnu/*.dll ../scripts/go/_internal/speaker-identification/ @@ -141,6 +142,19 @@ jobs: name: ${{ matrix.os }}-libs path: to-upload/ + - name: Test non-streaming decoding files with MedASR + shell: bash + run: | + cd scripts/go/_internal/non-streaming-medasr-ctc-decode-files + ls -lh + go mod tidy + cat go.mod + go build + ls -lh + + ./run.sh + rm -rf sherpa-onnx-medasr-* + - name: Test non-streaming decoding files with Omnilingual ASR shell: bash run: | diff --git a/go-api-examples/non-streaming-medasr-ctc-decode-files/go.mod b/go-api-examples/non-streaming-medasr-ctc-decode-files/go.mod new file mode 100644 index 0000000000..9053a1b0fd --- /dev/null +++ b/go-api-examples/non-streaming-medasr-ctc-decode-files/go.mod @@ -0,0 +1,3 @@ +module non-streaming-medasr-ctc-decode-files + +go 1.17 diff --git a/go-api-examples/non-streaming-medasr-ctc-decode-files/main.go b/go-api-examples/non-streaming-medasr-ctc-decode-files/main.go new file mode 100644 index 0000000000..67d658d463 --- /dev/null +++ b/go-api-examples/non-streaming-medasr-ctc-decode-files/main.go @@ -0,0 +1,97 @@ +package main + +import ( + "bytes" + "encoding/binary" + "log" + "os" + "strings" + + sherpa "github.com/k2-fsa/sherpa-onnx-go/sherpa_onnx" + "github.com/youpy/go-wav" +) + +func main() { + log.SetFlags(log.LstdFlags | log.Lmicroseconds) + + config := sherpa.OfflineRecognizerConfig{} + + config.ModelConfig.MedAsr.Model = "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/model.int8.onnx" + config.ModelConfig.Tokens = "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/tokens.txt" + + waveFilename := "./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/test_wavs/0.wav" + + samples, sampleRate := readWave(waveFilename) + + log.Println("Initializing recognizer (may take several seconds)") + recognizer := sherpa.NewOfflineRecognizer(&config) + log.Println("Recognizer created!") + defer sherpa.DeleteOfflineRecognizer(recognizer) + + log.Println("Start decoding!") + stream := sherpa.NewOfflineStream(recognizer) + defer sherpa.DeleteOfflineStream(stream) + + stream.AcceptWaveform(sampleRate, samples) + + recognizer.Decode(stream) + log.Println("Decoding done!") + result := stream.GetResult() + + log.Println("Text: " + strings.ToLower(result.Text)) +} + +func readWave(filename string) (samples []float32, sampleRate int) { + file, _ := os.Open(filename) + defer file.Close() + + reader := wav.NewReader(file) + format, err := reader.Format() + if err != nil { + log.Fatalf("Failed to read wave format") + } + + if format.AudioFormat != 1 { + log.Fatalf("Support only PCM format. Given: %v\n", format.AudioFormat) + } + + if format.NumChannels != 1 { + log.Fatalf("Support only 1 channel wave file. Given: %v\n", format.NumChannels) + } + + if format.BitsPerSample != 16 { + log.Fatalf("Support only 16-bit per sample. Given: %v\n", format.BitsPerSample) + } + + reader.Duration() // so that it initializes reader.Size + + buf := make([]byte, reader.Size) + n, err := reader.Read(buf) + if n != int(reader.Size) { + log.Fatalf("Failed to read %v bytes. Returned %v bytes\n", reader.Size, n) + } + + samples = samplesInt16ToFloat(buf) + sampleRate = int(format.SampleRate) + + return +} + +func samplesInt16ToFloat(inSamples []byte) []float32 { + numSamples := len(inSamples) / 2 + outSamples := make([]float32, numSamples) + + for i := 0; i != numSamples; i++ { + s := inSamples[i*2 : (i+1)*2] + + var s16 int16 + buf := bytes.NewReader(s) + err := binary.Read(buf, binary.LittleEndian, &s16) + if err != nil { + log.Fatal("Failed to parse 16-bit sample") + } + outSamples[i] = float32(s16) / 32768 + } + + return outSamples +} diff --git a/go-api-examples/non-streaming-medasr-ctc-decode-files/run.sh b/go-api-examples/non-streaming-medasr-ctc-decode-files/run.sh new file mode 100755 index 0000000000..270c6851eb --- /dev/null +++ b/go-api-examples/non-streaming-medasr-ctc-decode-files/run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -ex + +export CGO_ENABLED=1 + +if [ ! -f ./sherpa-onnx-medasr-ctc-en-int8-2025-12-25/tokens.txt ]; then + curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2 + tar xvf sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2 + rm sherpa-onnx-medasr-ctc-en-int8-2025-12-25.tar.bz2 +fi + +go mod tidy +go build +./non-streaming-medasr-ctc-decode-files diff --git a/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/.gitignore b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/.gitignore new file mode 100644 index 0000000000..f477ce343b --- /dev/null +++ b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/.gitignore @@ -0,0 +1 @@ +non-streaming-medasr-ctc-decode-files diff --git a/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod new file mode 100644 index 0000000000..d93c0a8113 --- /dev/null +++ b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod @@ -0,0 +1,15 @@ +module non-streaming-medasr-ctc-decode-files + +go 1.17 + +replace github.com/k2-fsa/sherpa-onnx-go/sherpa_onnx => ../ + +require ( + github.com/k2-fsa/sherpa-onnx-go/sherpa_onnx v0.0.0-00010101000000-000000000000 + github.com/youpy/go-wav v0.3.2 +) + +require ( + github.com/youpy/go-riff v0.1.0 // indirect + github.com/zaf/g711 v0.0.0-20190814101024-76a4a538f52b // indirect +) diff --git a/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/main.go b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/main.go new file mode 120000 index 0000000000..2bf87e853e --- /dev/null +++ b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/main.go @@ -0,0 +1 @@ +../../../../go-api-examples/non-streaming-medasr-ctc-decode-files/main.go \ No newline at end of file diff --git a/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/run.sh b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/run.sh new file mode 120000 index 0000000000..13ba7c9b9a --- /dev/null +++ b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/run.sh @@ -0,0 +1 @@ +../../../../go-api-examples/non-streaming-medasr-ctc-decode-files/run.sh \ No newline at end of file diff --git a/scripts/go/sherpa_onnx.go b/scripts/go/sherpa_onnx.go index 3e754f068b..47c7864c46 100644 --- a/scripts/go/sherpa_onnx.go +++ b/scripts/go/sherpa_onnx.go @@ -423,6 +423,10 @@ type OfflineOmnilingualAsrCtcModelConfig struct { Model string // Path to the model, e.g., model.onnx or model.int8.onnx } +type OfflineMedAsrCtcModelConfig struct { + Model string // Path to the model, e.g., model.onnx or model.int8.onnx +} + type OfflineDolphinModelConfig struct { Model string // Path to the model, e.g., model.onnx or model.int8.onnx } @@ -485,6 +489,7 @@ type OfflineModelConfig struct { Canary OfflineCanaryModelConfig WenetCtc OfflineWenetCtcModelConfig Omnilingual OfflineOmnilingualAsrCtcModelConfig + MedAsr OfflineMedAsrCtcModelConfig Tokens string // Path to tokens.txt // Number of threads to use for neural network computation @@ -589,6 +594,7 @@ func newCOfflineRecognizerConfig(config *OfflineRecognizerConfig) *C.struct_Sher c.model_config.wenet_ctc.model = C.CString(config.ModelConfig.WenetCtc.Model) c.model_config.omnilingual.model = C.CString(config.ModelConfig.Omnilingual.Model) + c.model_config.medasr.model = C.CString(config.ModelConfig.MedAsr.Model) c.model_config.tokens = C.CString(config.ModelConfig.Tokens) @@ -742,6 +748,11 @@ func freeCOfflineRecognizerConfig(c *C.struct_SherpaOnnxOfflineRecognizerConfig) c.model_config.wenet_ctc.model = nil } + if c.model_config.medasr.model != nil { + C.free(unsafe.Pointer(c.model_config.medasr.model)) + c.model_config.medasr.model = nil + } + if c.model_config.omnilingual.model != nil { C.free(unsafe.Pointer(c.model_config.omnilingual.model)) c.model_config.omnilingual.model = nil From 12d6b993751602950502679721da9bcdca990d7e Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Mon, 29 Dec 2025 12:45:58 +0800 Subject: [PATCH 2/2] Small fixes --- .../non-streaming-medasr-ctc-decode-files/go.mod | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod index d93c0a8113..7ee920cf15 100644 --- a/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod +++ b/scripts/go/_internal/non-streaming-medasr-ctc-decode-files/go.mod @@ -3,13 +3,3 @@ module non-streaming-medasr-ctc-decode-files go 1.17 replace github.com/k2-fsa/sherpa-onnx-go/sherpa_onnx => ../ - -require ( - github.com/k2-fsa/sherpa-onnx-go/sherpa_onnx v0.0.0-00010101000000-000000000000 - github.com/youpy/go-wav v0.3.2 -) - -require ( - github.com/youpy/go-riff v0.1.0 // indirect - github.com/zaf/g711 v0.0.0-20190814101024-76a4a538f52b // indirect -)