转录质量、自定义词汇与运行时统一¶
状态: 计划,2026-10-22。根据当前代码树(2.3.1)综合了 docs/research/model-watch.md 和 docs/research/custom-vocabulary.md。
摘要¶
Hex 的默认模型(ParakeetUnifiedEnglish)速度很快(在 Metal 上约 188 倍实时),并且在通用英语上准确(5.91% 8-set WER),但目前没有词汇输入,会将领域术语和姓名误识别为常见英语单词("Hex" -> "Hanks"、"Cappuccino" -> "Capuchin"、"OpenCode" -> "open code")。盲目地查找替换无法修复 "Hanks" 或 "Capuchin" 这类真实词冲突,否则会破坏合理句子。与此同时,会议中的实时转录正迁移到共享 TranscriptionEngine 上的滚动 Parakeet 分块处理(Moonshine 将从 src/meeting_live.rs 中移除),这使得语音命令(src/moonshine.rs)成为 ONNX Runtime + libmoonshine 技术栈的最后使用者。
Transcription quality plan (ordered by value / effort)
├── Phase 1: Term & false-replacement eval harness (2d)
│ └── Extends `hex benchmark-transcription` + corpus scripts with `expected_terms` and a term-free guard set
├── Phase 2: Shared vocabulary, Rune UI, and replacement fixes (4d)
│ └── App-wide vocabulary + "heard as" aliases in Settings, History 1-click add, #139/#177 fixes, OpenCode & meeting wiring
├── Phase 3: `transcribe-cpp` 0.2.4 -> 0.4.1 & catalog refresh (2d)
│ └── Unlocks `RunOptions::vocabulary`, Qwen3-ASR hints (#129), and `parakeet-ultra` (replaces Parakeet v3)
├── Phase 4: Parakeet greedy-decode phrase boost in `transcribe.cpp` (5d spike + 5d ship)
│ └── Host CPU logit biasing + SentencePiece tokenizer + margin gate (`"Hanks"` -> `"Hex"`, `"Capuchin"` -> `"Cappuccino"`)
├── Phase 5: In-call meeting transcripts & optional Apple live tail (3d)
│ └── Tightens rolling Parakeet pause cuts (6-10 s) with shared vocabulary; optional ~2% CPU `SpeechTranscriber` draft tail
└── Phase 6: Moonshine Streaming GGUF for voice commands (5d)
└── Replaces `libmoonshine` + ONNX Runtime + `download.moonshine.ai` with 199 MB Q8 GGUF on `transcribe-cpp`
所有阶段均保持的硬性不变量¶
- 听写绝不会因会议而延迟: 会议分块仅在
!parakeet::dictation_busy()时以 utility QoS 在TranscriptionEngine上运行,绝不中断实时流,并在 300 ms 保持阈值 + 200 ms 释放尾音内完成。 - 每个
Model只加载一个听写模型、一个活动流:transcribe-cpp0.4.1 仍强制每个Model只能有一个活动计算/流租约(Session::stream在并发使用时返回Error::Busy)。绝不会为会议或命令加载第二个 ParakeetModel(+0.74 GB RAM)。 - 默认仅本地,必要时严格使用 GPU: macOS 上使用 Metal(
src/parakeet.rs),Linux / Windows x64 上使用 Vulkan(src/transcription/local_transcriber.rs)。
阶段 1:评估语料库与基准测试门禁¶
- 目标: 在发布任何词汇、后处理或解码器更改之前,度量术语召回率和误替换回归。
- 更改:
- 在
src/transcription_benchmark.rs(hex benchmark-transcription)中扩展ClipDefinition,增加可选的expected_terms: Vec<String>,并添加--vocabulary <path>以便将词汇/别名列表加载到Parakeet::load_for_benchmark。 - 在
src/transcription_benchmark.rs的 JSONL 输出中新增两个汇总指标:term_recall:expected_terms出现在输出中的比例(大小写和空格归一化后)。false_replacements:当expected中不存在时,词汇术语出现在转录文本中的计数和比率。
- 构建一个由两部分组成的本地基准测试清单,复用
f4755e4中落地的语料库基础设施(scripts/dictation-corpus.sh和src/dictation_corpus_tests.rs,合并自test/dictation-corpus):- 目标术语集(约 100 个片段): 包含
Hex(包括真实的"Hanks"误识别)、Cappuccino("Capuchin"误识别)、OpenCode、Rune、Scrawl、Effect、Anomaly以及队友姓名的say语音、ElevenLabs 片段和 Kit 的真实录音。 - 无术语防护集(200 个 LibriSpeech
test-clean片段 + Kit 的无术语听写片段): 包含使用"Tom Hanks"和"Avatar"等常见词的合理句子,以捕获过度激进的偏置。
- 目标术语集(约 100 个片段): 包含
- 度量与门禁: 工具通过
cargo run --release -- benchmark-transcription端到端运行,并报告基线ParakeetUnifiedEnglishWER、term_recall、false_replacements、median_rtf、p95_clip_ms和/usr/bin/time -l峰值驻留内存。后续每个阶段的门禁为:术语无关集上的 WER 增量 <= +0.3 个百分点,误替换 <= 0.5%,且在 10 秒片段上的 p95 延迟增量 < 20 ms。 - 工作量: 2 天。
- 风险: 低。仅靠合成 TTS 片段会高估语音规则性;通过要求在清单中包含真实麦克风和会议误识别片段来缓解。
- 解锁: 为阶段 2、3 和 4 提供客观的 go/no-go 门禁。
阶段 2:共享词汇表、替换修复与 Rune 界面¶
- 目标: 让用户在一个地方定义姓名、行话和已知误识别,并且这些定义在所有模型、模式、听写和会议转录中都有效。
- 更改:
- 修复
src/dictation/text_replacements.rs中的错误(#139、#177):#177(CJK 从不匹配):phrase_boundary当前要求两侧都是!word_character(^\w$),这会拒绝无空格句子中的 CJK 匹配。仅当匹配短语本身以空格分隔的书写系统(拉丁/西里尔/希腊/数字)开头或结尾时,才要求词字符边界;CJK 字符自定界。#139(重叠匹配被跳过):如果较早的匹配因phrase_boundary失败,matcher.find_iter(text)会跳过同一规则的重复出现。从任何被拒绝的匹配之后的下一个 UTF-8 字符边界继续扫描。
- 数据模型(
src/app_settings.rs):- 向
AppSettings的settings.json添加pub vocabulary: Vec<VocabularyEntry>({ term: String, aliases: Vec<String> })。 - 在
MIGRATIONS中添加一次性迁移,将任何非空的transcription.recognition_hints和transcription_recents[*].recognition_hints(按逗号/换行拆分)导入vocabulary,并从transcription_models::validate中移除!model.supports_recognition_hints错误,以便在存在提示时切换模型不会失败。
- 向
- 流水线接入(
src/parakeet.rs、src/transcription/local_transcriber.rs、src/dictation_processor.rs、src/meeting_transcript.rs):- 模型提示: 将
vocabulary术语(上限 64 个术语,以防止 Whisper 静音幻觉,见 #108/#193)传递给supports_recognition_hints的模型。 - 全局别名替换: 将明确的
aliases -> term对(以及像"open code" -> "OpenCode"这样的多词复合连接)编译到共享的ReplacementSet中,在dictation_processor.rs、dictation_modes.rs以及meeting_transcript.rs中的滚动/最终分块上,先于特定模式的replacements运行。 - OpenCode 重写提示(
src/dictation_processor.rs): 当某个模式启用 OpenCode 重写时,追加一个紧凑的Vocabulary块("优先使用这些精确拼写,当某个词听起来像其中之一时:Hex(听到为:Hanks)、Cappuccino(听到为:Capuchin)、OpenCode、Rune、Scrawl、Effect…")。因为 LLM 能看到句子上下文,它能在不破坏普通文本的情况下解决真实词冲突("Hanks"、"Capuchin")。
- 模型提示: 将
- Rune 界面(
src/rune_ui/settings.rs、src/rune_ui/history.rs、src/desktop_i18n.rs):- 遵循
docs/design-system.md:将settings::dictation_section中仅限 Whisper 的Recognition hints行替换为对所有模型可见的Vocabularysection卡片。 - 组合现有
rune_ui/controls.rs组件:card_header带一个 GhostPLUSIconButton("添加术语")和一个 Secondary"导入…"/"导出…"操作(#160);行包含Term (e.g. Cappuccino)的TextInput和可选的Heard as (e.g. Capuchin),以及remove_button。 - 在
src/rune_ui/history.rs中,当raw_text与final_text不同或已被选中时,在detail_header中添加一个 Secondary"添加到词汇…"操作,预填充误听的短语。 - 在
src/desktop_i18n.rs中添加全部五种语言翻译,并在浅色和深色模式下更新--snap场景(mac-settings、history)。
- 遵循
- 度量与门禁:
- 在
src/dictation/text_replacements.rs中编写单元测试,覆盖 CJK 短语(#177)和重叠候选(#139)。 - 阶段 1 基准测试:对明确别名(
"open code" -> "OpenCode"、"scrawl"、"rune")达到 100% 召回率,并对 LLM 重写的"Hanks"/"Avatar"句子达到 100% 召回率;cargo test --bin hex rune_ui通过,且浅色/深色 golden 文件更新。 - 工作量: 4 天。
- 风险: 低。用户可能会将常见词输入为无条件别名(例如
"Hanks" -> "Hex");在阶段 4 中,当 Parakeet 处于活动状态时,通过将单字真实词冲突路由到声学余量门控来缓解,或者在别名是常见词典词时内联警告。 - 解锁: 将单一用户词汇输入到 Qwen3-ASR 提示(阶段 3)、Parakeet 解码器增强(阶段 4)和会议转录(阶段 5)中。
阶段 3:transcribe-cpp 升级(0.2.4 -> 0.4.1)与目录刷新¶
- 状态(2026-10-26): 依赖升级已完成且行为不变:词汇语料库上的转录结果相同,权重现在已使用 mmap 映射(在 Metal 上,峰值占用从约 0.9 GB 降至 0.15 GB)。识别提示(Hints)、目录刷新以及 Vulkan 预热验证仍有待完成。
- 目标: 将
transcribe-cpp升级到0.4.1,以解锁通用的RunOptions::vocabulary/prompt,启用 Qwen3-ASR 识别提示(#129),并用parakeet-ultra替换ParakeetV3。 - 变更:
- 依赖升级(
Cargo.toml、src/transcription/gguf_session.rs、src/parakeet.rs、src/transcription/local_transcriber.rs):- 将
Cargo.toml中全部三个目标条目(默认、Linuxvulkan、Windows x64vulkan)里的transcribe-cpp从=0.2.4升级到=0.4.1。 - 更新
model.capabilities()的调用点(src/transcription/gguf_session.rs:110、src/parakeet.rs:1073、src/transcription/local_transcriber.rs:154),以处理Result<Capabilities>。 - 用
0.4.1的通用RunOptions::vocabulary/prompt能力位(docs/prompting.md)替换仅限 Whisper 的RunExtension::Whisper提示接线,并在src/transcription_models.rs中将Qwen3Asr06B的supports_recognition_hints设置为true(#129)。
- 将
- 模型目录(
src/transcription_models.rs):- 添加
ParakeetUltra(handy-computer/parakeet-ultra-gguf、parakeet-ultra-Q8_0.gguf,约 740 MB,CC-BY-4.0,25 种语言):Moondream 对 v3 进行后训练得到的版本,将 LibriSpeech clean WER 从 1.94% 降至 1.80%(8 组榜单为 5.32%,而 v3 为 6.32%),并在自然停顿处切分长音频(30 秒片段)。 - 在
choices_for_runtime中,针对当前推荐ParakeetV3的 24 种非英语欧洲语言推荐ParakeetUltra;同时保持ParakeetV3在TranscriptionModelId中可反序列化,以便现有的settings.json文件能继续工作或干净迁移。
- 添加
- 测量与门禁:
- 在
ParakeetUnifiedEnglish上运行hex benchmark-transcription对比0.2.4与0.4.1:无 WER 回退,median_rtf和p95_clip_ms偏差在 5% 以内,且 8 秒流预热(STREAM_PREWARM_SAMPLES)在 Metal 和 Vulkan 上均通过。 - 使用阶段 2 的词汇提示,在英语/法语/普通话产品名称片段上验证
Qwen3Asr06B(#129)。 - 在基准清单上对比
ParakeetUltra与ParakeetV3(>30 秒片段上的 WER 和停顿切分)。 - 工作量: 2 天。
- 风险: 低。
0.4.1更改了各架构下的 C++ 内部实现;推送前必须在 macOS Metal 上验证预热和峰值 RSS。 - 解锁: 为阶段 4 提供
0.4.1的RunOptions::vocabulary管道和 C++ 基础。
阶段 4:Parakeet 贪心解码短语增强¶
- 目标: 在推理过程中,让 Parakeet 的声学解码器偏向用户的词汇,使
"Hex"、"Cappuccino"、"OpenCode"、"Rune"、"Scrawl"、"Effect"以及人名胜过发音相似的常见词("Hanks"、"Capuchin"),且无需调用 LLM 或使用第二个模型。 - 为什么这在 Parakeet 中可行:
- 在
transcribe.cpp(src/arch/parakeet/decoder.cpp)中,decode_rnnt_greedy(Unified English)、decode_tdt_greedy(v2/v3/ultra)以及流式 RNN-T 都在主机 CPU 上运行(在src/transcription/gguf_session.rs中,GPU 设备上的n_threads = 1)。 - 在每一步中,
joint_step将联合网络输出复制到主机端的std::vector<float> logits,应用log_softmax,并以blank_id = vocab选择argmax_range(token_logits, n_token_cls)。 - 变更:
- 步骤 4a:在本地
transcribe.cpp0.4.1 检出中进行 5 天 spike:- SentencePiece 编码器: 为存储在 GGUF 元数据中的 Parakeet 1,024 片 SentencePiece 词汇实现分词(替换
transcribe_tokenize中的INT_MIN存根),并生成大小写变体("Hex"、" hex"、"Cappuccino"、" cappuccino")。 - Aho-Corasick / 前缀 trie(字典树)浅融合(GPU-PB 风格,arXiv 2508.07014): 基于
RunOptions::vocabulary构建带有失败链接的 token 级前缀 trie。 - 声学裕度门控 + 前缀回滚: 在每个
joint_step,仅当logits[best_non_blank] - logits[t] <= margin(表明声学已经支持t)时,才将boost(例如 +1.5 到 +3.0 nats)应用于使 trie 前进的 tokent。为防止多 token 词条("Cappuccino"、"OpenCode")在后续子词未通过声学裕度门控时留下残缺的首个子词,需在处于活跃的多 token trie 前缀内部时保持一个影子预测器状态,并且仅在完整词条完成时提交它(在活跃前缀之外零额外计算)。
- SentencePiece 编码器: 为存储在 GGUF 元数据中的 Parakeet 1,024 片 SentencePiece 词汇实现分词(替换
- 步骤 4b:向上游提交 + fork 桥接(
Cargo.toml、src/parakeet.rs、src/transcription/local_transcriber.rs):- 将
Parakeet和LocalTranscriber接线,使settings.vocabulary中的词条传入RunOptions::vocabulary(包括离线run和with_stream两条路径)。 - 上游与 fork 策略: 向上游
handy-computer/transcribe.cpp提交一个 PR,填补docs/prompting.md和transcribe_tokenize中 Parakeet 目前为空的vocabulary槽位。在上游审查期间,携带一个指向anomalyco/transcribe.cpp的窄[patch.crates-io]git 补丁(固定修订版本,必要时更新nix/package.nix哈希),以便 Hex 立即发布,待上游发布后再回到 crates.io 的固定版本。 - 若贪心 spike 未达门禁时的后备方案: 在 Rust 中使用
Transcript::tokens(Token::p)以及transcribe_segments(src/parakeet.rs:1190)已返回的词时间戳,实现置信度门控的语音修正(phonetic snap),并采用 FluidAudio 风格的防护规则(<=4 个字符的词相似度 >=80%,含停用词时 >=85%)。
- 将
- 测量与门禁:
- 必须在
ParakeetUnifiedEnglish上通过阶段 1 门禁:词条召回率 >= 70%(包括"Hanks" -> "Hex"和"Capuchin" -> "Cappuccino"的真实片段),在 200 片段 LibriSpeech + 无词条防护集上的误替换率 <= 0.5%,整体 WER 变化 <= +0.3 个百分点,且每个片段的 p95 解码开销 < 5 毫秒。 - 工作量: 5 天(spike)+ 5 天(流式路径、
[patch.crates-io]、上游 PR)。 - 风险: 中。对短的单 token 词(
"Hex")过度增强可能会在发音相似的词("checks"、"text"、"necks")上造成误替换。缓解措施包括:对短词(<=4 个字符)收紧所需的声学裕度,并允许每个词条配置"heard as"别名来限制短词在何时进行增强。 - 解锁: 在热键听写和滚动会议转录中实现零延迟自定义词汇,且无需 OpenCode。
阶段 5:通话中的会议转录和实时草稿¶
- 目标: 让会议转录在通话期间(包括“会议”面板和
Option-Control-V会议粘贴中)保持准确且最新,而无需加载第二个 GGUF 模型或延迟听写。 - 与进行中工作(
ses_e992a1790ffej3W41HZ62GVxQb)的协调: - 另一个会话正在将通话中的副本/视图切换到共享
TranscriptionEngine上的滚动 Parakeet 分块,并从src/meeting_live.rs中移除 Moonshine。 - 变更:
- 更快的暂停感知滚动分块(
src/meeting_transcript.rs):- 目前
CHUNK_MIN = 10 s、CHUNK_TARGET = 20 s、CHUNK_MAX = 30 s(src/meeting_transcript.rs:36-40),这导致通话中的滚动转录落后实时语音 20-30 秒。 - 将
CHUNK_MIN降至5 s,CHUNK_TARGET降至8 s(为连续说话者保留CHUNK_MAX = 25 s和CHUNK_OVERLAP = 2 s)。在 Metal 上约 190 倍实时速度下,一个 8 秒分块在共享引擎线程上约需 42 ms,能远在听写的 300 ms 保持阈值 + 200 ms 释放尾部之内完成。
- 目前
- 滚动和最终会议分块中的词汇(
src/meeting_transcript.rs):- 将第 2 阶段的共享词汇替换和第 4 阶段的
RunOptions::vocabulary应用于滚动和最终会议分块,使"Hex"、"Cappuccino"、"OpenCode"和参与者姓名在第一次滚动时即正确。
- 将第 2 阶段的共享词汇替换和第 4 阶段的
- 通过 Apple
SpeechTranscriber的可选亚秒级易失尾部(src/apple_speech.rs、src/meeting_live.rs、macOS 26+):- 一旦从
meeting_live.rs中移除 Moonshine,唯一的间隙就是暂停切分落地前当前正在说的 0-8 秒句子。 - 如果 Kit 希望为该活动句子提供实时的逐字字幕,可将每个轨道的 100 ms Int16 缓冲区流式送入 Apple 设备端
SpeechAnalyzer/SpeechTranscriber(docs/plans/meeting-live-transcription.md),在rolling.covered_ms之后将TranscriptPhase::Updated/Completed写入transcript.live.ndjson。滚动 Parakeet 会在每个 5-8 秒分块完成时覆盖该尾部。
- 一旦从
- 测量与门槛:
- 通过
meeting_echo_replay回放录制的说话者模式通话:- 暂停后的滚动 Parakeet 回合延迟从约 20 秒降至 p50 <= 6 秒、p95 <= 10 秒。
- 说话者回声泄漏(
You误报)或丢弃本地You回合的数量零增长。 - 会议录制期间的听写延迟保持在基线水平(8 秒听写片段上 p50 约 70 ms、p95 < 110 ms)。
- 与旧的双流 Moonshine 实时工作进程相比,峰值常驻内存下降 约 400 MB(如果启用 Apple
SpeechTranscriber(约 2% CPU),额外模型内存保持为 0 MB)。
- 工作量: 3 天(1 天用于滚动节奏 + 词汇;如需添加
SpeechTranscriber易失尾部则为 2 天)。 - 风险: 低。更频繁的 5-8 秒分块会略微增加 Metal 唤醒(两个轨道约 15 个分块/分钟 = 每分钟约 0.6 秒 GPU 工作,约占空比 1%),但只要
parakeet::dictation_busy()为真,仍会立即让出。 - 解锁事项: 从会议中完全移除 Moonshine,使第 6 阶段能够仅围绕命令简化
src/moonshine.rs。
阶段 6:用于语音命令的 Moonshine 流式 GGUF¶
- 目标: 通过
transcribe-cpp,用moonshine-streaming-smallQ8_0 GGUF 替换 ONNX Runtime +libmoonshineC 库(src/moonshine.rs)和download.moonshine.ai下载器。 - 为何命令使用 Moonshine GGUF 而非流式 Parakeet:
- 常开命令无法在不阻塞听写的情况下共享听写模型的单个
Session::stream租约,而第二个 ParakeetModel会额外占用 +740 MB 内存,并持续进行 5.6 秒左侧上下文的 GPU 重计算。 - 在命令延迟(<300 ms)方面,
moonshine-streaming-small(199 MB Q8_0,8-set WER 7.84%,LibriSpeech clean 2.54%)优于 160 ms 下的 Parakeet Unified(WER 8.44%),并在 Metal 上以 129 倍实时速度、在 CPU 上以 64 倍实时速度运行。 - 变更:
- 将
moonshine-streaming-small-Q8_0.gguf(199 MB,handy-computer/moonshine-streaming-small-gguf,固定修订版和 SHA-256)添加到 Hex 的 Hugging Face 模型下载器(src/transcription_models.rs)。 - 基于
transcribe-cpp的moonshine_streaming架构重写src/moonshine.rs:- 由于
transcribe-cpp的 Moonshine 流返回已提交/暂定文本,并将单个流限制在 81.9 秒内,且没有内置 VAD 行事件,因此使用 Hex 现有的 16 kHzPauseSegmenter(或transcribe-cpp内置的 Silero VAD v6.2)驱动行生命周期。 - 在语音起始时启动流(
TranscriptPhase::Started),当暂定/已提交文本变化时发出TranscriptPhase::Updated(保持低延迟的语音分隔听写触发),并在暂停时完成(TranscriptPhase::Completed),用于src/recognition.rs中的常规命令解析。
- 由于
- 删除
libmoonshine.dylib动态加载(libloading)、src/main.rs中的MOONSHINE_ORT_SINGLE_THREAD、8 文件.ort清单以及download.moonshine.ai主机要求。 - 测量与门槛:
- 回放
moonshine_lab命令夹具套件(cargo run --profile moonshine-lab -- ...),比较 ONNX Moonshine 与 GGUF Moonshine small:- 命令匹配准确率和唤醒短语召回率 >= ONNX 基线。
- 更新延迟 p50 <= 35 ms、p95 <= 70 ms。
- 活动命令 CPU <= 单个核心的 20%(而当前 ONNX 单线程为 22%),常驻内存 <= 300 MB(从约 400 MB 下降)。
- 工作量: 5 天。
- 风险: 中等。命令响应性取决于将 VAD 段映射到
Started/Updated/Completed行时的端点检测挂起时间;在删除 ONNX 路径之前,根据moonshine_lab夹具进行调优可防止回归。 - 解锁事项: 整个代码库中只有一个推理引擎(
transcribe.cpp)和一个模型下载器(带 SHA-256 收据的 Hugging Face)。
需 Kit 决策的事项¶
- 共享词汇 UI 应放在哪里?
- 建议: 将共享的 词汇 卡片放在 设置 -> 听写 中(对每个模型可见,替换仅限 Whisper 的
Recognition hints行),并在历史记录条目上提供一键 “添加到词汇” 按钮,同时将每种模式的 更正 保留在 模式 中,用于特定于模式的文本规则。 - 为第 4 阶段的 Parakeet 短语增强携带一个临时的
anomalyco/transcribe.cpp[patch.crates-io]fork,还是等待上游合并? - 建议: 在上游 PR 审查期间携带一个固定的
[patch.crates-io]fork,以便一旦 5 天的专项工作通过基准门槛,Hex 就能立即获得 Parakeet 词汇增强。 - 移除 Moonshine 后,通话中的会议怎么办:5-8 秒滚动 Parakeet 是否足够,还是也添加 Apple
SpeechTranscriber(约 2% CPU、0 MB 内存)易失尾部? - 建议: 先发布带共享词汇的 5-8 秒暂停切分滚动 Parakeet(1 天);仅当您希望看到单词在暂停前于句中实时出现时,才添加 Apple
SpeechTranscriber易失尾部。 - 在第 3 阶段用
parakeet-ultra替换选择器中的Parakeet v3,还是两者都列出? - 建议: 在选择器中用
parakeet-ultra替换Parakeet v3(保持现有settings.json文件中的parakeet_v3可用),因为parakeet-ultra具有相同的 740 MB Q8 大小和 25 种语言覆盖范围,且 WER 严格更优,并具备暂停感知的长音频分段能力。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 hex19/hex