语音输入
使用
在助手输入框输入 /settings 打开统一设置,再选择“语音输入”标签。识别默认关闭,各控件修改后立即自动保存于客户端 config/system/system-asr.json,与百炼 TTS 配置分开;切换标签或关闭设置无需额外保存。AppKey、AccessKey ID 与 Secret 可以逐项填写,开始识别时才校验完整凭据。
- 在阿里云智能语音交互控制台创建项目,取得 AppKey,选择支持 16 kHz 的一句话识别模型。识别语种与方言在项目控制台设置,API 不接收游戏语言作为模型选择参数。
- 填写项目 AppKey、有 NLS 权限的阿里云 AccessKey ID / AccessKey Secret 和识别地域(上海 / 北京 / 深圳),开启即可,修改自动保存。这里不能使用百炼
DASHSCOPE_API_KEY。临时 Token 由程序自动获取,不再手动填写。 - 按住 F8 录音,松开结束;可在游戏“控制 → 系统助手”改键,支持键盘/鼠标及修饰键。有可见通知时优先录入通知指令,无通知时打开当前模式的助手;在完整或简约助手内按下则保留草稿。原版聊天栏里有通知时也可录入通知指令,其他页面不触发。也可继续点击“语音输入”或输入
/listen/“语音输入”,再点击结束。看到“正在录音”后说话,中间结果在输入框上方或通知底部显示。 - 松开按键或点击“结束录音”等待最终识别,结果追加到输入框草稿;默认确认后按 Enter 发送。可在语音识别设置中开启“识别后立即发送”,最终识别成功后自动发送合并后的草稿,按键、按钮和
/listen均适用;中间识别结果不发送。录音最多 60 秒,到时自动结束。识别本身不调用聊天模型,发送草稿后才进入已有路由。
autoSend 保存在客户端 config/system/system-asr.json,默认关闭;旧配置缺少此字段时仍需手动发送。自动发送复用普通发送入口,继续遵守指令路由、请求忙碌和输入法保护;若当时无法发送,文字保留在输入框,不排队重试。识别期间修改草稿、取消或离开界面不会自动发送,窗口失焦时最终结果也不会自动发送。
按键自动重复不会创建新任务,松开只结束自己启动的录音。尚未开启语音输入时按键打开设置页,不录音、不发起收费请求。“取消”、关闭界面、切换页面、窗口失焦、发送其他请求、断线或撤销绑定都会取消当前识别 session 并关闭麦克风。迟到回调不写入其他界面或新连接。识别期间如果手动修改草稿,不覆盖修改后的内容,需重新发起语音输入。开始识别会停止当前朗读,后续到达的通知仍按原有 TTS 逻辑处理。
凭据留空时分别读取客户端进程的 ALIYUN_NLS_APP_KEY、ALIYUN_AK_ID、ALIYUN_AK_SECRET;环境变量值不写回配置。页面填写的凭据以明文保存,Secret 控件遮挡显示。配置、音频与识别结果不作为用量报告发给 MC 服务端;只有发送到主聊天的文字或匹配通知按钮后的结构化操作才进入正常助手请求。录音只在内存中分片流转,不保存 WAV 或上传到 OSS。
配置字段如下,留空字段可由上述环境变量补齐:
{
"enabled": false,
"provider": "aliyun-nls",
"appKey": "",
"accessKeyId": "",
"accessKeySecret": "",
"region": "shanghai",
"autoSend": false
}
自动鉴权
依据官方 HTTP / HTTPS Token 签发协议,客户端在实际识别的工作线程中调用 GET https://nls-meta.cn-shanghai.aliyuncs.com/ 的 CreateToken,使用 2019-02-28 版本、UTC 时间、唯一 nonce 和 POP HMAC-SHA1 签名。签发地域固定为 cn-shanghai,与所选识别网关地域无关。打开设置、逐字保存配置和本地凭据检查均不会签发 Token。
AliyunNlsToken 跨识别 session 共享一份内存缓存,读取 Token.Id 与 Unix 秒单位的 Token.ExpireTime,剩余有效期不足两分钟时在下次识别前重新签发。缓存只保存凭据指纹和 Token,不保留多份旧凭据;凭据变化后重新获取,刷新请求串行合并。Token 不写配置、存档或网络包,签名 URL、Secret、Token 和上游响应正文不记录到日志。该实现仅使用 JDK 网络与加密 API,不增加 SDK 依赖。
签发请求 10 秒超时、响应最多 64 KiB,随录音 session 中断取消。若识别 WebSocket 握手返回 401 / 403,清除对应 Token 并重新签发、连接一次;此时尚未发送 StartRecognition。已经提交的识别任务失败时不会自动重试,Token 被拒则使其缓存失效,下一次录音重新获取。凭据、权限、时钟或签发错误显示本地化提示,不把上游响应中的敏感信息直接展示。
通知语音操作
通知完全展开后,按住同一个语音键说“确定”“关闭”“下一个”“下一页”“查看详情”“领取奖励”或当前按钮文案,松开后处理最终结果。“关闭”“下一个”“下一页”可确认并移除当前通知,队列继续显示下一条;若当前确有“下一页”按钮,优先执行该按钮的翻页操作。无需先打开聊天栏,录音不抢占游戏焦点;聊天栏内仍支持原有鼠标按钮。开始录音会停止当前通知播报,通知在录音及等待最终识别期间继续保留,本身没有自动关闭倒计时。确认、切换、隐藏通知、切换界面、窗口失焦、登出或撤销绑定会取消其识别 session;迟到结果只能作用于原通知和原连接。
优先匹配当前通知按钮,匹配成功复用鼠标点击的受信回调和忙碌检查,不调用聊天模型。未命中、相似度不足、多个按钮匹配或复杂表达会打开主聊天框,立即复用普通指令与意图路由;若助手正忙,则把识别内容留作主聊天框草稿。通知回退明确请求进入主聊天路由,因此不受仅针对普通聊天录音的 autoSend 开关影响。回退时保留原通知,不猜测要操作哪个奖励。
按钮以固定本地化键声明,语句与对应 TF-IDF 稀疏向量来自 assets/system/routing/notification-buttons.json,当前文案也自动参与匹配。客户端资源包可在相同路径追加按钮键及 zh / en 例句;重载时按资源包层级合并,较高层同键同语种覆盖较低层,并使内存索引失效。当前按钮组合与语言不变时复用已生成的向量,不保存录音或玩家原文。新增按钮无需修改 confirm/details/open 分支,只需声明文案键和受信回调,可选补充例句。具体匹配边界见轻量路由。
FTB 任务完成后如有可领奖励,通知提供“领取奖励”。仅一项普通奖励时使用该玩家的短期引用直接走既有领奖工具;多项或自选奖励先显示详情供明确选择。已自动领取、被阻止或不可领取的奖励不生成动作,实际执行仍重新校验玩家、队伍、任务和奖励版本。通知排队过久导致引用失效时需重新查看详情。
FTB 启动概览的“查看任务”以及新手礼包的“领取礼包”“查看礼包”同样声明固定按钮键和双语例句,可直接语音操作。识别只匹配当前显示的按钮;领取仍使用该通知的短期礼包引用,过期后先查看礼包刷新,不会按礼包名称生成领取授权。
协议与扩展
依据一句话识别 API接入 NLS WebSocket,使用 JDK HttpClient,无新增 SDK、原生库或模型文件。HttpTransport.webSocket 复用网络工具的客户端生命周期、握手时限和取消;Token 沿用阿里云官方 Java SDK 的 X-NLS-Token 握手请求头,不记录凭据或上游异常正文。
连接 wss://nls-gateway-cn-<region>.aliyuncs.com/ws/v1,发送 SpeechRecognizer.StartRecognition,麦克风在后台打开后立即采集,不等云端握手;等待 RecognitionStarted 后上传缓冲及后续音频,避免吞掉开头。松开按键立即停止本地采集,已缓冲的内容仍在本次请求内提交。发送 16 kHz / 16-bit / 单声道 / 小端 PCM 二进制帧,启用中间结果、标点和 ITN。停止后只发送一次 StopRecognition,以 RecognitionCompleted.payload.result 为最终文本,不将中间结果累计相加。
语音输入默认关闭,Simple Voice Chat(SVC)是可选客户端依赖,服务端无需安装。设置页显示是否检测到 SVC:未安装时使用 JDK Java Sound 默认输入设备;安装时通过反射加载隔离适配器,沿用 SVC 选定的麦克风、OpenAL/Java Sound 后端选择及 OpenAL 失败后退回 Java Sound 的处理。直接以 16 kHz、每帧 320 个样本采集,既不经过 Opus,也不需从 48 kHz 重采样。原有按钮和按键共用同一采集路径。
已核对 SVC 2.6.26+26.1.2 实际依赖 JAR:公开 VoicechatClientApi 没有独立启停麦克风方法,ClientSoundEvent 又在 SVC 自身 PTT/语音激活筛选之后,不能作为独立按键录音源。因此 compat/voicechat/VoicechatRecognitionCapture 封装其内部 ALMicrophone / JavaxMicrophone,单独打开设备,不读取或修改 SVC 自身录音线程。公开插件事件只负责在助手采集期间取消语聊发送,结束后保留 250ms 尾部抑制;适配/插件安装失败时提示错误并不开始录音。没有安装 SVC 时不注册插件、不加载适配器或任何 SVC 类型。内部接口存在版本敏感性,升级 SVC 后应重新核对;若设备不允许同时打开,显示麦克风错误,不抢占语聊设备。
设备打开与音频读取在一个有界守护录音执行器中执行,网络在独立识别执行器中执行,主线程仅操作界面和取消。连接期间音频仅在有界内存队列保存,不落盘;录音上限 60 秒 / 1,920,000 PCM 字节。不支持 16 kHz 单声道或被系统禁止访问时给出本地提示。单条响应最多 64 KiB,结果最多 2000 UTF-16 单元;连接 10 秒超时、整体 90 秒上限、停止后最多再等待 15 秒。失败不自动重试收费任务。
手动停止与音频入队共用锁,停止后排空已缓冲的 PCM 即返回 EOF,不等待设备读取或关闭;自然录音结束也在设备关闭前发布 EOF,最后一帧在终止标志可见后复核。独立守护计时器对 session 执行 90 秒整体 / 15 秒收尾限制,终态和计时代次阻止迟到回调覆盖成功、错误或取消结果。执行器繁忙及后台失败会结束等待,日志保留本地错误码与完整异常堆栈(含 Caused by),不主动记录凭据、音频或识别文字。
AsrProvider 位于 speech.asr,协议层不依赖 MC。供应商由 speech.AsrProviders 的普通工厂 Map 管理,内置键为 aliyun-nls。扩展在客户端初始化时调用 AsrProviders.register(name, factory),不参与 MC 注册表生命周期,AsrProviders.create(provider) 按配置字符串精确查找并创建独占实例,不自动补命名空间。供应商实现纯本地的 validate、recognize(Request, AudioSource, Consumer<String>, Runnable requestStarted) 和 close;requestStarted 在鉴权、连接完成后、首次发送识别命令前调用,开始统计本次识别,详见注册表速查。当前配置凭据结构面向 NLS,增加不同鉴权方式的供应商时需扩展相应配置表单。可选供应商自己的单位计费也需单独适配,不套用 NLS 次数单价。
用量与费用
同一用量界面显示本账号的 ASR 尝试、失败/取消、未完成、未估价次数及估算金额,按客户端账号 UUID 存在本机 config/system/speech-usage/<UUID>.json,跨服务器累计,不随 revoke、forget 清空。不向服务端上报语音用量,不存在其他玩家的语音统计;管理员全服视图也只汇总 AI。服务端 AI 快照使用 StreamCodec,当前协议保持 1,客户端与服务端需一起更新。
按用户指定的 3.5 元 / 1000 次,成功收到 RecognitionCompleted 的请求估算 0.0035 元 / 次。接口不提供 Token 用量,不伪造输入/输出 Token。失败、取消或断线的请求可能已经被云端计费,保留为未估价;估算只含已知成功请求,以阿里云账单为准,不包含免费额度或折扣。本地用量不作为扣款、奖励或服务端限额依据。
价格使用客户端 config/system/system-speech-pricing.json 的 CALLS 单位。内置默认 JSON 给上海、北京、深圳各一条用户指定的参考单价,并非三个地域在线价格的重新核对。已有价格配置不会被覆盖或自动增加条目,缺少所用地域时需手动在 rates 中加入条目,否则 ASR 继续记录次数但标为未估价:
{
"provider": "aliyun-nls",
"model": "sentence-recognition",
"region": "shanghai",
"unit": "CALLS",
"units": 1000,
"input": 3.5,
"output": 0
}
修改价格后通过客户端 F3+T 或重启客户端加载,不重算历史金额。首次发送识别命令前本地记账,Token 签发与握手失败不计 ASR 尝试;完成回调只归并一次,取消或换服后的迟到结果仍属于原账号;未收到完成的尝试维持“未完成”。同账号的 TTS / ASR 更新串行写入,不再经过网络报告与服务端限流。详见个人语音数据边界。
验证边界
2026-10-31 同步 1.21.1 实际堆栈对应的语音价格表修正:PRICE 与日志器先于 Table.CODEC 和立即加载配置的 INSTANCE 初始化,金额支持 JSON 数字及十进制字符串。原问题会在识别成功后的本地费用统计阶段阻止最终文本交付;账本现统一隔离统计计算的 RuntimeException / LinkageError,记录完整堆栈并保留上一次快照,不中断识别或播报。若当前进程已发生类初始化失败,更新后必须重启客户端,资源重载无法恢复 JVM 中已失效的类。
本次只执行编译、打包和静态检查,未启动 Minecraft、打开麦克风或调用收费接口;真实设备兼容性、NLS 鉴权与转写效果尚未进行运行时验收。