From 80f3f2a4e9ffedbe31f5d3c4e014cf07439a99cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=B8=E9=9B=81?= Date: Sat, 30 May 2026 02:27:59 +0800 Subject: [PATCH] fix: SenseVoice+spk_model crash and torchaudio>=2.11 compatibility 1. auto_model.py: When ASR model (e.g. SenseVoice) doesn't produce timestamps, automatically fall back to vad_segment mode for speaker diarization instead of crashing. Fixes #2945. 2. load_utils.py: Add soundfile as fallback when torchaudio.load fails (torchaudio>=2.11 requires torchcodec). Falls through to ffmpeg only if soundfile also fails. --- funasr/auto/auto_model.py | 3 +++ funasr/utils/load_utils.py | 15 +++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/funasr/auto/auto_model.py b/funasr/auto/auto_model.py index 46d8b42b7..3820782db 100644 --- a/funasr/auto/auto_model.py +++ b/funasr/auto/auto_model.py @@ -819,6 +819,9 @@ class AutoModel: ) # del result['spk_embedding'] sv_output = postprocess(all_segments, None, labels, spk_embedding.cpu()) + if self.spk_mode == "punc_segment" and "timestamp" not in result and "timestamps" not in result: + logging.warning("No timestamps in ASR result (e.g. SenseVoice), falling back to vad_segment mode for speaker diarization.") + self.spk_mode = "vad_segment" if self.spk_mode == "vad_segment": # recover sentence_list sentence_list = [] for rest, vadsegment in zip(restored_data, vadsegments): diff --git a/funasr/utils/load_utils.py b/funasr/utils/load_utils.py index ce8525b74..03acf0df4 100644 --- a/funasr/utils/load_utils.py +++ b/funasr/utils/load_utils.py @@ -113,10 +113,17 @@ def load_audio_text_image_video( if kwargs.get("reduce_channels", True): data_or_path_or_list = data_or_path_or_list.mean(0) except: - data_or_path_or_list = _load_audio_ffmpeg(data_or_path_or_list, sr=fs) - data_or_path_or_list = torch.from_numpy( - data_or_path_or_list - ).squeeze() # [n_samples,] + try: + import soundfile as sf + data_np, audio_fs = sf.read(data_or_path_or_list, dtype="float32") + data_or_path_or_list = torch.from_numpy(data_np).squeeze() + if data_or_path_or_list.ndim > 1 and kwargs.get("reduce_channels", True): + data_or_path_or_list = data_or_path_or_list.mean(-1) + except: + data_or_path_or_list = _load_audio_ffmpeg(data_or_path_or_list, sr=fs) + data_or_path_or_list = torch.from_numpy( + data_or_path_or_list + ).squeeze() # [n_samples,] elif data_type == "text" and tokenizer is not None: with open(data_or_path_or_list, "r") as f: data_or_path_or_list = tokenizer.encode(f.read().strip())