From 2117b036496e2d3dba2d1e8f8a0cd4d50eb2bfc5 Mon Sep 17 00:00:00 2001 From: txfs19260817 Date: Fri, 16 Oct 2026 22:38:33 -0700 Subject: [PATCH] fix(nano): avoid duplicate fs and preserve audio loading errors --- .../fun_asr_nano/model.py | 3 ++- funasr/models/fun_asr_nano/model.py | 3 ++- tests/test_fun_asr_nano_train_opts.py | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/examples/industrial_data_pretraining/fun_asr_nano/model.py b/examples/industrial_data_pretraining/fun_asr_nano/model.py index 85ca785375..2e50e9e432 100644 --- a/examples/industrial_data_pretraining/fun_asr_nano/model.py +++ b/examples/industrial_data_pretraining/fun_asr_nano/model.py @@ -403,12 +403,13 @@ def data_load_speech(self, contents: dict, tokenizer, frontend, meta_data={}, ** try: time1 = time.perf_counter() data_src = load_audio_text_image_video( - sub_str, fs=frontend.fs, **kwargs + sub_str, **{**kwargs, "fs": frontend.fs} ) time2 = time.perf_counter() meta_data["load_data"] = f"{time2 - time1:0.3f}" except Exception as e: logging.error(f"Loading wav failed! {str(e)}, {traceback.format_exc()}") + raise speech, speech_lengths = extract_fbank( data_src, diff --git a/funasr/models/fun_asr_nano/model.py b/funasr/models/fun_asr_nano/model.py index 049ba6a06b..78d75ce59d 100644 --- a/funasr/models/fun_asr_nano/model.py +++ b/funasr/models/fun_asr_nano/model.py @@ -549,12 +549,13 @@ def data_load_speech(self, contents: dict, tokenizer, frontend, meta_data={}, ** try: time1 = time.perf_counter() data_src = load_audio_text_image_video( - sub_str, fs=frontend.fs, **kwargs + sub_str, **{**kwargs, "fs": frontend.fs} ) time2 = time.perf_counter() meta_data["load_data"] = f"{time2 - time1:0.3f}" except Exception as e: logging.error(f"Loading wav failed! {str(e)}, {traceback.format_exc()}") + raise speech, speech_lengths = extract_fbank( data_src, diff --git a/tests/test_fun_asr_nano_train_opts.py b/tests/test_fun_asr_nano_train_opts.py index df4d293889..967860db3f 100644 --- a/tests/test_fun_asr_nano_train_opts.py +++ b/tests/test_fun_asr_nano_train_opts.py @@ -6,6 +6,7 @@ class and the recipe's model.py, imported by path). CPU-only, no weights: tiny s import re import sys import types +from unittest.mock import Mock import pytest import torch @@ -80,6 +81,32 @@ def model_class(request): return funasr_model.FunASRNano if request.param == "funasr" else _load_recipe_model() +@pytest.mark.parametrize("options", [{}, {"fs": 16000}, {"fs": 48000, "audio_fs": 48000}]) +@pytest.mark.parametrize("fail", [False, True]) +def test_audio_loading(model_class, monkeypatch, options, fail): + module = sys.modules[model_class.__module__] + error = OSError("Cannot decode audio") + loader = Mock(side_effect=error) if fail else Mock(return_value=torch.zeros(160)) + extract = Mock(return_value=(torch.zeros(1, 4, 80), torch.tensor([4]))) + monkeypatch.setattr(module, "load_audio_text_image_video", loader) + monkeypatch.setattr(module, "extract_fbank", extract) + args = ( + types.SimpleNamespace(use_low_frame_rate=False), + {"system": [""], "user": ["<|startofspeech|>!sample.wav<|endofspeech|>"], "assistant": [""]}, + types.SimpleNamespace(encode=lambda text: [1]), + types.SimpleNamespace(fs=16000, frame_shift=10, lfr_n=1), + ) + if fail: + with pytest.raises(OSError) as caught: + model_class.data_load_speech(*args, meta_data={}, **options) + assert caught.value is error + extract.assert_not_called() + else: + output = model_class.data_load_speech(*args, meta_data={}, **options) + assert output["speech"].shape == (1, 4, 80) + loader.assert_called_once_with("sample.wav", **{**options, "fs": 16000}) + + @pytest.fixture def build(monkeypatch, model_class): """``build(llm_conf) -> FunASRNano`` on the CPU, with the transformers loaders stubbed."""