diff --git a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt index 7001eac..3001ac0 100644 --- a/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt +++ b/app/src/main/java/com/k2fsa/sherpa/onnx/MainActivity.kt @@ -159,12 +159,11 @@ class MainActivity : AppCompatActivity() { // Embedding model candidates, tried in order. Place one in the external // models dir (preferred) or at the ROOT of assets/. Download: // https://github.com/k2-fsa/sherpa-onnx/releases/tag/speaker-recongition-models + // 仅 CAM++(2026-09-16 用户拍板:eres2net 系识别效果太差,整体退役)。 + // 单模型单空间:滚动/快检/权威判定共用 CAM++;fastReady()=false 时所有 + // fast 路径自动回落准确注册表(阈值 0.5/0.42,更严更稳) private val speakerModels = listOf( - // 主选:CAM++ 7.1M,中英训练,3D-Speaker 榜单 EER 优于 eres2net 系, - // v1.13 声纹提取器架构无关(读 ONNX 元数据),换文件即生效 "3dspeaker_speech_campplus_sv_zh_en_16k-common_advanced.onnx", - "3dspeaker_speech_eres2netv2_sv_zh-cn_16k-common.onnx", // accurate fallback - "3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx", // smaller/faster ) private var activeSpeakerModel: String? = null private val speakerThreshold = 0.5f @@ -464,9 +463,6 @@ class MainActivity : AppCompatActivity() { initOfflineRecognizer() setStatus(getString(R.string.loading_speaker)) initSpeakerIdentification() - if (speakersEnabled) { - initFastSpeakerModel() - } runOnUiThread { modelsLoaded = true if (!historyMode) recordButton.isEnabled = true @@ -1232,23 +1228,6 @@ class MainActivity : AppCompatActivity() { activeSpeakerModel = null } - // E:轻量声纹模型(eres2net base,列表末位)专供滚动换人检测,推理快 ~4 倍。 - // 找不到该文件(或准确模型本来就是 base)时跳过,滚动检测自动回退准确模型。 - // 注:换 CAM++ 主选后 fast 空间暂仍用 base(独立 registry 镜像,互不污染); - // CAM++ 足够小,后续想让它兼职 fast 只需把末位换成同文件。 - private fun initFastSpeakerModel() { - val fastName = speakerModels.last() - if (activeSpeakerModel == fastName) return // 准确模型已是 base - try { - SpeakerRecognition.initFastExtractor( - null, speakerModelFile(fastName).absolutePath - ) - Log.i(TAG, "fast speaker model ready: $fastName") - } catch (t: Throwable) { - Log.i(TAG, "fast model '$fastName' not found, rolling falls back to v2") - } - } - // 点击行首说话人标签(ClickableSpan)→ 命名或改名。 // internalKey:该行的内部声纹键("S0"/真名);null=归属未定,提示稍后再命名。 private fun showNameSpeakerDialog(internalKey: String?) { @@ -1860,9 +1839,11 @@ class MainActivity : AppCompatActivity() { uiHandler.post { adoptSwitchLabel(serial, name) } } name == null || score < verdictFallbackMin -> { - // 确认无人:发新号 + 双空间注册(纯净素材) - val fastEmb = SpeakerRecognition.computeEmbeddingFast( - samples, sampleRateInHz) + // 确认无人:发新号注册(纯净素材);fastReady=false(单 CAM++)时 + // 镜像无意义,跳过额外计算 + val fastEmb = if (SpeakerRecognition.fastReady()) { + SpeakerRecognition.computeEmbeddingFast(samples, sampleRateInHz) + } else null val label = SpeakerRecognition.nextAutoLabel().also { SpeakerRecognition.registry.addAuto(it, acc) if (fastEmb != null) { diff --git a/app/src/main/java/com/k2fsa/sherpa/onnx/SpeakerEmbedding.kt b/app/src/main/java/com/k2fsa/sherpa/onnx/SpeakerEmbedding.kt index 270c2cf..889f3e3 100644 --- a/app/src/main/java/com/k2fsa/sherpa/onnx/SpeakerEmbedding.kt +++ b/app/src/main/java/com/k2fsa/sherpa/onnx/SpeakerEmbedding.kt @@ -221,9 +221,10 @@ class SpeakerRegistry { // Singleton holder shared by the UI thread, recording thread and the rolling // speaker-check thread. // -// 双模型方案(E):准确模型(eres2netv2)负责 endpoint 权威判定与注册; -// 轻量模型(eres2net base,可选)只负责滚动换人检测(推理快 ~4 倍)。 -// ⚠ 两个模型的 embedding 不互通:各自配一份 registry,注册时双写镜像。 +// 单模型方案(2026-09-16 用户拍板):仅 CAM++;eres2net 系整体退役。 +// fastReady()=false 时:computeEmbeddingFast 回落 CAM++,滚动检索直接走 +// 准确注册表(speakerThreshold 0.5 / verdictFallbackMin 0.42)。镜像注册 +// 机制保留但不再有调用者(fastEmb 门控后恒 null)。 // --------------------------------------------------------------------------- object SpeakerRecognition { @Volatile private var _extractor: SpeakerEmbeddingExtractor? = null