TRTC 开麦语音识别 + 房间流行语

方木先生
    分享互动规则

    TRTC 开麦语音识别 + 房间流行语(Buzzword)开发者说明

    本文说明 trtc_speech_recognizer 插件与主工程 PopularPhraseUtil 流行语命中如何协作,以及为提高开麦说话时命中准确率已做的优化与后续可演进方向。面向 Flutter / iOS 原生同事,尽量通俗。


    1. 整体在做什么

    用户在语音房内开麦说话,本地用 TRTC 采集到的 PCM 喂给 Apple Speech(SFSpeechRecognizer,zh_CN),实时得到整句转写文本;业务侧用后台下发的流行语词表做子串匹配,命中后播特效(飘字 / 表情雨等)。

    插件不负责流行语逻辑,只负责「把麦上音频变成字符串」;流行语算法在主工程 lib/utils/util_popular_phrase.dart,由 RoomBuzzwordViewModelonTextUpdated 里调用。

    flowchart LR
      subgraph iOS["iOS 原生"]
        TRTC["TRTC 本地处理后音频帧"]
        PCM["PCM → SFSpeechAudioBufferRecognitionRequest"]
        ASR["Apple Speech zh_CN"]
        TRTC --> PCM --> ASR
      end
      subgraph Flutter["Flutter 业务"]
        EVT["EventChannel 文本流"]
        MATCH["PopularPhraseUtil.matchPopularPhrase"]
        FX["特效 / clearTranscript"]
        EVT --> MATCH --> FX
      end
      ASR -->|"bestTranscription.formattedString"| EVT
    

    2. 关键代码位置(便于跳转维护)

    职责路径
    插件 Dart API、与业务对齐的静态入口packages/trtc_speech_recognizer/lib/trtc_speech_recognizer.dart
    iOS:TRTC 音频帧 → Speech、清空 transcript、事件发送packages/trtc_speech_recognizer/ios/Classes/TrtcSpeechRecognizerPlugin.swift
    流行语词表拉取、开麦检测、命中后特效lib/modules/room/view-model/view_model_room_buzzword.dart
    子串匹配 + 规范化(本次优化核心)lib/utils/util_popular_phrase.dart
    词表模型lib/modules/room/model/model_buzzword.dart

    3. 开麦检测到命中:时序(简化)

    sequenceDiagram
      participant VM as RoomBuzzwordViewModel
      participant TR as TrtcSpeechRecognizer
      participant iOS as TrtcSpeechRecognizerPlugin
      participant U as PopularPhraseUtil
    
      VM->>TR: initialize / startDetection
      TR->>iOS: MethodChannel + EventChannel 监听
      loop 音频帧
        iOS->>iOS: appendPCMToSpeech
        iOS-->>VM: onTextUpdated(整段转写)
        VM->>U: matchPopularPhrase(text)
        alt 命中
          VM->>VM: onKeywordHitHandle
          VM->>TR: clearTranscript
          TR->>iOS: 结束当前 request,新建 request,忽略旧 final
          iOS-->>VM: onTextUpdated("")
        end
      end
    

    要点:

    • shouldReportPartialResults = true,因此 onTextUpdated 会频繁回调(中间结果 + 最终结果),有利于尽早命中流行语。
    • 命中后 clearTranscript:结束当前识别段、新建 SFSpeechAudioBufferRecognitionRequest,并 ignoreNextFinalResult 防止清空后旧任务最后一次 final 把旧句子又推回来(交互上避免「闪回」)。

    4. 原流行语算法与痛点

    4.1 原逻辑(概念)

    1. 对词表 keywordsname 字符串长度从长到短排序,避免「牛」盖住「牛马」。
    2. 对识别文本 trim 后,做 contains(关键词) 子串匹配。

    4.2 主要痛点:ASR 文本形态与词表不一致

    Apple Speech 的 SFTranscription.formattedString 在中文场景下,经常在字与字之间插入空格(排版/分词风格)。例如用户说的语义是「牛马」,识别结果可能是 牛 马。此时:

    • 词表配置为 牛马
    • 旧逻辑:"牛 马".contains("牛马")false漏命中

    同类问题还包括:零宽字符、从运营后台复制带来的 BOM、全角英文字母与半角不一致、英文大小写等。


    5. 本次已落地的优化(提高命中率)

    PopularPhraseUtil 中增加统一入口 normalizeForPopularPhraseMatch,在匹配前对「识别文本」和「关键词」做同一套规范化,再执行 contains

    1. 去掉空白:合并并移除 \s+,消除中文间空格导致的漏匹配。
    2. 去掉零宽字符与 BOM\u200B-\u200D\uFEFF
    3. 全角 ASCII → 半角:Unicode FF01FF5E 映射到 217E(常见运营配置全角符号场景)。
    4. 英文统一小写toLowerCase(),避免大小写造成的漏匹配。

    排序规则改为按 「规范化后的关键词长度」 从长到短,与真实匹配语义一致。

    实现见:lib/utils/util_popular_phrase.dartnormalizeForPopularPhraseMatchmatchPopularPhrase

    5.1 优化前后对照(示意)

    识别文本(示例)词表关键词旧逻辑新逻辑
    牛 马牛马不命中命中
    牛\u200B马牛马不命中命中
    HELLOhello视情况不命中命中(全角转半角 + 小写)

    6. 性能与交互说明

    • 词表规模:当前是 O(n) 遍历 + 每次对关键词做一次规范化;n 为词表条数。一般房间流行语量级较小,可接受。若未来上千条,可考虑:
      • initBuzzwordList 拉取词表后预计算并缓存每条 name 的规范化结果;
      • 或使用 Aho-Corasick / trie 做多模式匹配(需评估包体积与维护成本)。
    • 重复命中:每次命中会 clearTranscript,相当于消费掉当前整段上下文;若产品需要「同一句连说两次都触发」,要单独设计冷却或分句策略(当前文档不展开)。

    7. 仍未解决的一类问题:ASR「听错字」

    若识别结果把「牛马」听成「流马」等 语义错误,仅靠字符串 contains 无法纠正。可选演进(需产品 / 后台配合):

    • 后台为每条流行语配置 别名 / 常见误识别变体
    • 或引入 拼音 / 编辑距离 的模糊匹配(注意误触风险与性能);
    • 或在 requiresOnDeviceRecognition、模型版本、采样链路上调优(属 iOS 侧策略,需真机 A/B)。

    8. 自测建议(开发自测清单)

    1. iOS 真机进房、开麦,说一条词表中连续两字的流行语,观察 Log:onTextUpdated 是否出现带空格的中间结果,并确认仍能命中。
    2. 在后台将关键词配为 全角英文,口播半角,确认命中。
    3. 连续快速说同一流行语,确认 clearTranscript 后 UI 不闪回旧句(依赖插件侧 ignoreNextFinalResult)。

    9. 文档与代码变更摘要

    • 文档位置:仓库根目录本文件 TRTC_SPEECH_BUZZWORD_DEVELOPER.md
    • 代码变更lib/utils/util_popular_phrase.dart — 新增规范化方法并用于 matchPopularPhrase;插件与 ViewModel 调用链不变。

    若后续要把「别名词表」或「模糊匹配」也产品化,建议在本文件追加一节「数据契约」说明后台 JSON 字段约定,避免客户端与配置平台理解不一致。

    评论 0

    支持 @用户名 提醒对方(需为站内已注册用户名);回复仅支持一层楼中楼。

    登录后发表评论、回复与 @ 提及。

    举报

    举报会匿名发送给管理员审核。

    • 暂无评论,来发表第一条。

    码谱 · The Digital Atelier · 技术内容社区