From 12f008a4c19408b3773e059f3fb35589e3a12d17 Mon Sep 17 00:00:00 2001 From: liwenhao2 Date: Wed, 16 Sep 2026 17:08:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A3=B0=E7=BA=B9=E4=BB=85=E7=95=99=20CAM++(?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=8B=8D=E6=9D=BF:eres2net=20=E7=B3=BB?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E6=95=88=E6=9E=9C=E5=A4=AA=E5=B7=AE=E6=95=B4?= =?UTF-8?q?=E4=BD=93=E9=80=80=E5=BD=B9):speakerModels=20=E5=8D=95=E6=9D=A1?= =?UTF-8?q?;initFastSpeakerModel=20=E5=88=A0=E9=99=A4;=E5=8D=95=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=8D=95=E7=A9=BA=E9=97=B4=E2=80=94=E2=80=94fastReady?= =?UTF-8?q?=3Dfalse=20=E6=97=B6=E5=85=A8=E9=83=A8=20fast=20=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E8=87=AA=E5=8A=A8=E5=9B=9E=E8=90=BD=E5=87=86=E7=A1=AE?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E8=A1=A8(0.5/0.42=20=E6=9B=B4=E4=B8=A5),?= =?UTF-8?q?=E6=BB=9A=E5=8A=A8/=E5=BF=AB=E6=A3=80/=E6=9D=83=E5=A8=81?= =?UTF-8?q?=E5=88=A4=E5=AE=9A=E5=85=B1=E7=94=A8=20CAM++;deferredNaming=20?= =?UTF-8?q?=E9=95=9C=E5=83=8F=E8=AE=A1=E7=AE=97=E9=97=A8=E6=8E=A7=E8=B7=B3?= =?UTF-8?q?=E8=BF=87;=E4=BB=A3=E4=BB=B7=3D=E6=AF=8F=E6=AC=A1=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E6=A3=80=E6=9F=A5=E6=8D=A2=20CAM++=20=E6=8E=A8?= =?UTF-8?q?=E7=90=86(=E6=A3=80=E6=9F=A5=E7=BA=BF=E7=A8=8B=E4=B8=B2?= =?UTF-8?q?=E8=A1=8C,1s=20=E8=8A=82=E6=8B=8D=E4=B8=8B=E5=8F=AF=E6=89=BF?= =?UTF-8?q?=E5=8F=97);=E8=AE=BE=E5=A4=87=20eres2net=20=E4=B8=A4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=B7=B2=E6=97=A0=E5=BC=95=E7=94=A8=E5=8F=AF=E5=88=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/k2fsa/sherpa/onnx/MainActivity.kt | 35 +++++-------------- .../com/k2fsa/sherpa/onnx/SpeakerEmbedding.kt | 7 ++-- 2 files changed, 12 insertions(+), 30 deletions(-) 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