当前最新版本:v2.5.5,已经上传到pypi,有需要的同学可以下载安装来体验一下。
安装:pip install oddasr
运行:oddasr
Demo: http://localhost:9002
默认启动只支持2路实时转写,再加1路离线转写。可通过自行修改配置文件中的最大实例数来放大。
自定义配置启动
oddasr --config config.json
项目地址:https://github.com/oddmeta/oddasr
文档地址:https://oddmeta.net/docs/oddasr/
一、本次更新的亮点
本周的核心工作集中在说话人分离(Speaker Diarization)的配置化与请求级可控上,同时围绕实时转写首字时延 / 返回速度、低配硬件可运行性、Web 前端体验做了多处优化,并修复了 WebSocket 在 HTTPS 环境下的兼容性问题。
这个版本里主要是这几个功能:
- 对说话人分离做了一些增强,并让客户端可以指定:自动估计说话人数量、自动估计时的说话人数量搜索上界、合并相似说话人的余弦阈值,以及说话人分离时的分离粒度。这几个接口在OpenAI的接口里没有,所以我是跟之前的
response_format那样,给做了自定义的参数,具体请参考下面的这个表格。 - 转写时延统计给做了一些优化:让花掉的每一毫秒都清清楚楚,方便大家统计时延的瓶颈到底在什么地方,也方便后续可能的一些优化方向。
- 实时转写最终文本响应优化:delta文本500毫秒,completed文本 5 秒上限。不过这个调整响应是快了,但是带来的一个副作用是有些比较长的句子可能会被拆分到两个completed中,同时也会在一定程度上增加CPU的耗用。
二、新功能(Feat)
下面是更新的具体的新功能。
1. 说话人分离 4 个核心参数落地
新增 preset_spk_num / max_num_spks / merge_thr / spk_mode 四参数,打通了 配置文件 → 离线转写 API → Web 前端 的完整链路。
| 参数 | 默认值 | 作用 | 对应 FunASR 内部机制 |
|---|---|---|---|
preset_spk_num |
0 |
0=自动估计说话人数量;>0=强制指定数量(oracle) |
生成期参数,不触发模型重建 |
max_num_spks |
15 |
自动估计时的说话人数量搜索上界 | SpectralCluster |
merge_thr |
0.78 |
合并相似说话人的余弦阈值 | ClusterBackend.cb_kwargs |
spk_mode |
punc_segment |
分离粒度:punc_segment / vad_segment / default |
标点分段 / VAD 分段 |
- 配置文件(
odd_asr_config.py/docs/oddasr-speaker-diarization-config.md):- 4 个核心参数详解,每个标注对应的 FunASR 内部机制
- 4 个配置示例(自动估计 / 强制 2 人 / 限制最多 4 人 / 调整阈值与粒度)
- 参数生效机制表(生效时机、是否触发模型重建)
- 重要说明(SV 模型 vs Diarization 模型、
enable行为、动态开启、后端限制)
- 离线转写 API(
router/api.py):- 通过
preset_spk_num / max_num_spks / merge_thr / spk_mode表单参数按请求自定义 - 参数校验:整数参数用
isdigit()过滤负数;merge_thr校验范围(0, 1];spk_mode校验枚举值 - 未传或非法 →
None(不覆盖配置值) - 动态开启 spk 时保存实例上的 4 个原值,请求结束后在
finally中恢复 - 生效时机:
preset_spk_num为生成时参数(不触发重建),其余 3 个在 cache key 变化时重建模型
- 通过
- Web 前端(
templates/index.html):- 离线转写界面新增 4 个可选参数输入
- 仅在
response_format支持说话人分离时启用(json / verbose_json / spk / diarized_json)
2. 转写全流程时延统计
为转写流程中的每一个重点功能添加了毫秒级时延统计,覆盖:
- 流式转写:
TwoPassASR.stream_generate、各后端stream_generate - 离线精修:
offline_refine整体耗时 + 分段统计(normalize_audio/transcribe/ 标点恢复) - 最终化:
TwoPassASR.finalize总耗时 - API 层:请求处理各环节耗时
统计通过 logger.debug / logger.info 输出,便于定位性能瓶颈,也方便未来的进一步优化。
三、性能优化(Opt)
这次更新加涉及的一些实时、流式转写相关的优化。
1. 2-Pass 最大时间间隔降至 5 秒
max_audio_samples 从 57600000(1 小时)下调为 80000(5 秒 = 5 × 16000),强制加速实时流式转写最终结果的返回,显著缩短等待时间。
2. 降低默认 Paraformer 模型初始化数量(08-03)
- 实时转写:
max_instance从4→2 - 离线转写:
max_instance从2→1
这个默认最大实例的调整主要还是针对我自己的这个十年前的老笔记本(跑不动4路),降低内存与显存占用,让硬件配置较差的电脑也能顺利运行。
3. Web 界面按钮合并
将流式转写和文件流式转写的「开始 / 结束」按钮合并,简化操作逻辑。
四、问题修复(Fix)
1. 修复 HTTPS 与 WebSocket 混用导致的 Mixed Content 拦截
当网页通过 HTTPS 访问时,WebSocket 地址自动升级为 wss://,避免浏览器安全策略拦截。
需要注意的是,我自己其实是把 OddASR 部署在我自己的电脑上,然后利用 frp 再接到我的 99 元/年的阿里云2H2G的超低配云主机上的,所以在另一层还需要用nginx 来做一个反向路由才能用起来。若您对此方案感兴趣的话,可以私聊我,我把反向代理的代码发您。
2. 修复文档链接失效
更新 README / README_en / app.py 中的失效文档链接。
五、涉及文件
| 分类 | 文件 |
|---|---|
| 配置 | odd_asr_config.py |
| API | router/api.py |
| 模型 | models/paraformer_asr.py、models/sensevoice_funasr.py、models/moonshine_asr.py、models/sensevoice_asr.py、models/two_pass_asr.py |
| 逻辑 | logic/odd_asr_instance_pool.py、logic/odd_asr_stream_handler.py |
| 工具 | utils/audio.py、utils/formatters.py |
| 前端 | templates/index.html |
| 文档 | README.md、README_en.md、docs/oddasr-api-guideline.md、docs/oddasr-speaker-diarization-config.md |
| 打包 | setup.py(版本号 2.5.1 → 2.5.2,工作区已至 2.5.5) |
六、提交记录
| 日期 | 哈希 | 说明 |
|---|---|---|
| 08-08 | b33135b |
Web 前端离线转写加入说话人分离可选参数 |
| 08-08 | 00e9865 |
将 4 个说话人分离参数暴露到离线转写 API |
| 08-08 | 83757dd |
新增说话人分离配置与文档 |
| 08-07 | 3668991 |
Web 界面流式 / 文件流式按钮合并 |
| 08-07 | d7fc291 |
修复 HTTPS + WebSocket 混用被拦截 |
| 08-04 | 61b6526 |
降低默认 Paraformer 模型初始化数量 |
| 08-04 | 0dc6ebd |
2-Pass 最大时间间隔降至 5 秒 |
| 08-04 | 4bfe14f |
修复失效的文档链接 |
| 08-04 | 6efa5fe |
转写全流程时延统计 |
升级建议
- 使用说话人分离的用户,可在
config.json的model_options.*.spk下配置preset_spk_num等参数,或在离线转写请求中按需传参。 - 低配硬件用户可直接使用新的默认实例数,无需额外改动。
- 实时转写用户可感受更快的最终结果返回:delta文本500MS,completed文本 5 秒上限(不过这个调整响应是快了,但是带来的一个副作用是有些比较长的句子可能会被拆分到两个completed中,同时也会在一定程度上增加CPU的耗用)。

本次更新的核心工作集中在**说话人分离(Speaker Diarization)**的配置化与请求级可控上,同时围绕**实时转写首字时延 / 返回速度**、**低配硬件可运行性**、**Web 前端体验**做了多处优化,并修复了 WebSocket 在 HTTPS 环境下的兼容性问题。