Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions .github/scripts/test-python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ log() {
echo -e "$(date '+%Y-%m-%d %H:%M:%S') (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $*"
}

log "test Moonshine v2"

curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
tar xvf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
rm sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2

ls -lh sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27

python3 ./python-api-examples/offline-moonshine-decode-files-v2.py

rm -rf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27
Comment on lines +13 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and reduce redundancy, consider using variables for the model archive and directory names. This makes it easier to update the model version in the future. The ls command also appears to be for debugging and could be removed from the script.

Suggested change
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
tar xvf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
rm sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
ls -lh sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27
python3 ./python-api-examples/offline-moonshine-decode-files-v2.py
rm -rf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27
MODEL_ARCHIVE="sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2"
MODEL_DIR="sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27"
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/${MODEL_ARCHIVE}
tar xvf "${MODEL_ARCHIVE}"
rm "${MODEL_ARCHIVE}"
python3 ./python-api-examples/offline-moonshine-decode-files-v2.py
rm -rf "${MODEL_DIR}"


log "test FireRedASR CTC"

curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-fire-red-asr2-ctc-zh_en-int8-2026-02-25.tar.bz2
Expand Down
79 changes: 79 additions & 0 deletions python-api-examples/offline-moonshine-decode-files-v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3

"""
This file shows how to use a non-streaming Moonshine model from
https://github.com/usefulsensors/moonshine
to decode files.

Please download model files from
https://github.com/k2-fsa/sherpa-onnx/releases/tag/asr-models

For instance,

wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
tar xvf sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
rm sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27.tar.bz2
"""

import datetime as dt
from pathlib import Path
Comment on lines +18 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To support more accurate performance measurement with time.perf_counter(), please import the time module.

Suggested change
import datetime as dt
from pathlib import Path
import datetime as dt
import time
from pathlib import Path


import sherpa_onnx
import soundfile as sf


def create_recognizer():
encoder = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/encoder_model.ort"
decoder = (
"./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/decoder_model_merged.ort"
)
tokens = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/tokens.txt"
test_wav = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/test_wavs/0.wav"
Comment on lines +26 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve readability and maintainability, you can define the model directory path once and reuse it to construct the full paths for the model files. This avoids repeating the long directory name and makes the code cleaner.

Suggested change
encoder = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/encoder_model.ort"
decoder = (
"./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/decoder_model_merged.ort"
)
tokens = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/tokens.txt"
test_wav = "./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27/test_wavs/0.wav"
model_dir = Path("./sherpa-onnx-moonshine-tiny-en-quantized-2026-02-27")
encoder = model_dir / "encoder_model.ort"
decoder = model_dir / "decoder_model_merged.ort"
tokens = model_dir / "tokens.txt"
test_wav = model_dir / "test_wavs/0.wav"


if not Path(encoder).is_file() or not Path(test_wav).is_file():
raise ValueError(
"""Please download model files from
https://github.com/k2-fsa/sherpa-onnx/releases/tag/asr-models
"""
)
return (
sherpa_onnx.OfflineRecognizer.from_moonshine_v2(
encoder=encoder,
decoder=decoder,
tokens=tokens,
debug=False, # Set to True to see more logs
),
test_wav,
)


def main():
recognizer, wave_filename = create_recognizer()

audio, sample_rate = sf.read(wave_filename, dtype="float32", always_2d=True)
audio = audio[:, 0] # only use the first channel

# audio is a 1-D float32 numpy array normalized to the range [-1, 1]
# sample_rate does not need to be 16000 Hz

start_t = dt.datetime.now()

stream = recognizer.create_stream()
stream.accept_waveform(sample_rate, audio)
recognizer.decode_stream(stream)

end_t = dt.datetime.now()
elapsed_seconds = (end_t - start_t).total_seconds()
Comment on lines +59 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For measuring performance, time.perf_counter() is generally more suitable than datetime.datetime.now(). perf_counter() provides a high-resolution monotonic clock that is not affected by system time changes, making it ideal for timing short-duration intervals.

Suggested change
start_t = dt.datetime.now()
stream = recognizer.create_stream()
stream.accept_waveform(sample_rate, audio)
recognizer.decode_stream(stream)
end_t = dt.datetime.now()
elapsed_seconds = (end_t - start_t).total_seconds()
start_t = time.perf_counter()
stream = recognizer.create_stream()
stream.accept_waveform(sample_rate, audio)
recognizer.decode_stream(stream)
end_t = time.perf_counter()
elapsed_seconds = end_t - start_t

duration = audio.shape[-1] / sample_rate
rtf = elapsed_seconds / duration

print(stream.result)
print(wave_filename)
print("Text:", stream.result.text)
print(f"Audio duration:\t{duration:.3f} s")
print(f"Elapsed:\t{elapsed_seconds:.3f} s")
print(f"RTF = {elapsed_seconds:.3f}/{duration:.3f} = {rtf:.3f}")


if __name__ == "__main__":
main()
6 changes: 3 additions & 3 deletions sherpa-onnx/python/csrc/offline-moonshine-model-config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ void PybindOfflineMoonshineModelConfig(py::module *m) {
.def(py::init<const std::string &, const std::string &,
const std::string &, const std::string &,
const std::string &>(),
py::arg("preprocessor") = {}, py::arg("encoder") = {},
py::arg("uncached_decoder") = {}, py::arg("cached_decoder") = {},
py::arg("merged_decoder") = {})
py::arg("preprocessor") = "", py::arg("encoder") = "",
py::arg("uncached_decoder") = "", py::arg("cached_decoder") = "",
py::arg("merged_decoder") = "")
.def_readwrite("preprocessor", &PyClass::preprocessor)
.def_readwrite("encoder", &PyClass::encoder)
.def_readwrite("uncached_decoder", &PyClass::uncached_decoder)
Expand Down
Loading