# 同声翻译改走微软端到端 > 2026-10-18。只覆盖翻译页的同声模式(`simultaneous`)。本文只做设计,不改代码。 > 端到端依据 iOS 集成文档《同声传译简介》第 9.3、9.6 节。拼接时的识别依据安卓海外文档《实时语音转写》第 8.2、9.3 节(iOS《实时语音转写简介》只写了微软模式必填 `language_name`,没有语种表)。合成依据安卓海外文档《在线语音合成》的微软发音人表。 > 同声这一条覆盖 [科大讯飞SparkChain-全面替换第三方-落地文档.md](科大讯飞SparkChain-全面替换第三方-落地文档.md) 第 5.1 节里「表外拆成星火听写」的写法。面对面、通话、音视频、EMAI 不在本文范围。 ## 结论 两端语种都在微软同传表里:只开一条 `AST`,机房 `RegionMSFT`(安卓 `RegionType.MSFT_TYPE`)。识别、翻译、合成由这一条会话完成。 源或目标是中文、粤语、爱尔兰语:微软同传表没有这三语,改走拼接。拼接的识别必须是微软实时转写 `RTASR(RegionMSFT)`,用 `language_name` 指定语种。不要用星火听写 `ASR`(`zh_cn` / `cn_cbm` / `iat`),也不要用新加坡、欧洲机房那两张转写表(`ist_open`、`ist_mul_sp`、`ga_IE`)。 拼接的合成用 `OnlineTTS(RegionMSFT)`,发音人用微软神经音色。不要用 `xiaoyan`、`x_xiaoyan`、`x_Catherine`,也不要打 `tts-api.xfyun.cn`。 ## 现在为什么一种声音念所有语言 同声在讯飞听写成功之后,是三段接起来的,没有用到 `AST`。 1. `_startSparkListen` 调 `SparkChainSession.startListen`,只做听写。 2. 整句文本再走原来的翻译。 3. `playTranslatedText` 算出的 `voiceName` 在 `_sparkListen` 分支被丢掉,`_playSparkTts` 只把目标语种短码传给 `SparkChainSession.speak`。 原生合成不看音色表: | 端 | 英语 | 其余语种 | |---|---|---| | iOS `ClassicTts`,打 `tts-api.xfyun.cn` | `x2_catherine` | `xiaoyan` | | Android `OnlineTTS` | `x_Catherine` | `x_xiaoyan`(爱尔兰语例外,用 `ga-IE-OrlaNeural`) | 日语、韩语、法语都会用中文晓燕念出来。`getIflytekTTSLanguageSpecs()` 里按语种分好的发音人没有接到这条播报上。那张表是讯飞发音人,本方案也不再用。 ## 目标链路 麦克风 PCM 仍由现在的耳机麦或手机麦采集,SDK 不自己开麦。采集、保活、播放路由保持现有调用点。 ``` 耳机麦 / 手机麦 PCM │ 16 kHz / 16 bit / 单声道,每 40ms 1280 字节 ▼ AST(RegionMSFT) start(源语种, "pcm_s16le", 16000) use_tts = true target_lang = 目标语种 tts_target_lang = 目标语种 tts_speaker = 该目标语种的默认发音人 │ ├─ resType=asr / trans → 原文、译文上屏(流式,不再发翻译请求) └─ resType=tts → ttsResult.audio 交给现有 PcmStreamPlayer ``` iOS: ```objc AST *ast = [[AST alloc] initWithregion:RegionMSFT delegate:self]; [ast addStringParam:@"target_lang" value:@"en"]; [ast addBoolParam:@"use_tts" value:YES]; [ast addStringParam:@"tts_target_lang" value:@"en"]; [ast addStringParam:@"tts_speaker" value:@"JennyNeural"]; [ast start:@"ja" audioEncoding:@"pcm_s16le" sampleRate:16000 userInfo:tag]; ``` 安卓用同一个机房枚举和同一组参数名。这条端到端会话的 `tts_speaker` 用第 9.6 节的短名(`JennyNeural`)。`en-US-JennyNeural` 是拼接路径里 `OnlineTTS` 的写法,不要填进 `AST`。 方向固定为用户选的源 → 目标。不要用识别回来的语种对调方向。 停的顺序不变:先停推流和 `AST.stop(NO)`,再关耳机麦,再放保活。 ## 语种和音色 源语种、目标语种都必须在下表里。默认发音人取该行的第一个;同行其余名字是可换的音色,换的时候整段会话重开,不要在 `write` 过程中改 `tts_speaker`。 界面短码和表里的 `language` 一致的直接用。应用里的 `zh` 不要写成 `cn` 再送进微软会话:微软这张表没有中文。 | 语种 | language | 默认发音人 | 还可选 | |---|---|---|---| | 阿拉伯语 | ar | AbdullahNeural | AliNeural、AmalNeural、AmanyNeural、AminaNeural、AyshaNeural、BasselNeural、FahedNeural、FatimaNeural、HamdanNeural、HamedNeural、HediNeural、ImanNeural、IsmaelNeural、JamalNeural、LailaNeural、LaithNeural、LaylaNeural、MaryamNeural、MoazNeural、MounaNeural、NouraNeural、OmarNeural、RamiNeural、RanaNeural、ReemNeural、SalehNeural、SalmaNeural、SanaNeural、ShakirNeural、TaimNeural、ZariyahNeural | | 保加利亚语 | bg | BorislavNeural | KalinaNeural | | 孟加拉语 | bn | BashkarNeural | NabanitaNeural、PradeepNeural、TanishaaNeural | | 加泰罗尼亚语 | ca | AlbaNeural | EnricNeural、JoanaNeural | | 捷克语 | cs | AntoninNeural | VlastaNeural | | 丹麦语 | da | ChristelNeural | JeppeNeural | | 德语 | de | AmalaNeural | BerndNeural、ChristophNeural、ConradNeural、ElkeNeural、GiselaNeural、IngridNeural、JanNeural、JonasNeural、KasperNeural、KatjaNeural、KillianNeural、KlarissaNeural、KlausNeural、LeniNeural、LouisaNeural、MajaNeural、RalfNeural、TanjaNeural | | 希腊语 | el | AthinaNeural | NestorasNeural | | 英语 | en | JennyNeural | GuyNeural、AriaNeural、DavisNeural、JaneNeural、JasonNeural、NancyNeural、TonyNeural、WayneNeural、WilliamNeural、RyanNeural、SoniaNeural、LibbyNeural、NatashaNeural、ClaraNeural、LiamNeural、NeerjaNeural、PrabhatNeural、LunaNeural | | 西班牙语 | es | ElviraNeural | AlvaroNeural、AbrilNeural、ArnauNeural、DarioNeural、ElenaNeural、TomasNeural、DaliaNeural、JorgeNeural、PalomaNeural、AlonsoNeural | | 爱沙尼亚语 | et | AnuNeural | KertNeural | | 波斯语 | fa | DilaraNeural | FaridNeural | | 芬兰语 | fi | HarriNeural | NooraNeural、SelmaNeural | | 法语 | fr | DeniseNeural | HenriNeural、AlainNeural、BrigitteNeural、ClaudeNeural、SylvieNeural、JeanNeural、AntoineNeural | | 印地语 | hi | MadhurNeural | SwaraNeural | | 匈牙利语 | hu | NoemiNeural | TamasNeural | | 印尼语 | id | ArdiNeural | GadisNeural | | 意大利语 | it | ElsaNeural | IsabellaNeural、DiegoNeural、BenignoNeural、FabiolaNeural、GianniNeural | | 日语 | ja | NanamiNeural | KeitaNeural、AoiNeural、DaichiNeural、MayuNeural、NaokiNeural、ShioriNeural | | 韩语 | ko | SunHiNeural | InJoonNeural、BongJinNeural、HyunsuNeural、JiMinNeural、SeoHyeonNeural | | 立陶宛语 | lt | LeonasNeural | OnaNeural | | 拉脱维亚语 | lv | EveritaNeural | NilsNeural | | 马来语 | ms | OsmanNeural | YasminNeural | | 荷兰语 | nl | ArnaudNeural | ColetteNeural、FennaNeural、MaartenNeural | | 波兰语 | pl | AgnieszkaNeural | MarekNeural、ZofiaNeural | | 葡萄牙语 | pt | AntonioNeural | BrendaNeural、DuarteNeural、FranciscaNeural、RaquelNeural、YaraNeural | | 罗马尼亚语 | ro | AlinaNeural | EmilNeural | | 俄语 | ru | DariyaNeural | DmitryNeural、SvetlanaNeural | | 斯洛伐克语 | sk | LukasNeural | ViktoriaNeural | | 斯洛文尼亚语 | sl | PetraNeural | RokNeural | | 瑞典语 | sv | HilleviNeural | MattiasNeural、SofieNeural | | 斯瓦希里语 | sw | DaudiNeural | RafikiNeural、RehemaNeural、ZuriNeural | | 泰米尔语 | ta | AnbuNeural | KaniNeural、KumarNeural、PallaviNeural | | 泰语 | th | AcharaNeural | NiwatNeural、PremwadeeNeural | | 土耳其语 | tr | AhmetNeural | EmelNeural | | 乌克兰语 | uk | OstapNeural | PolinaNeural | | 乌尔都语 | ur | AsadNeural | GulNeural、SalmanNeural、UzmaNeural | | 越南语 | vi | HoaiMyNeural | NamMinhNeural | 文档没有给这些发音人标性别。默认列只是每行的第一个名字,用来保证换语言就换音色。 ## 中文、粤语、爱尔兰语:拼接,但识别走微软 微软同传表没有这三语。源或目标有其中一种时,不启 `AST`,改成三段: ``` 耳机麦 / 手机麦 PCM ▼ RTASR(RegionMSFT) 只识别源语种 lang = "msft" 固定值,不要把 zh-CN 填进 lang accent = "mandarin" 固定值 domain = "ist_mul_msft" 固定值 language_name = 下表 真正的语种 ▼ 整句文本翻译 不再次开识别 ▼ OnlineTTS(RegionMSFT) 按目标语种选微软神经音色 ▼ 现有 PcmStreamPlayer ``` 安卓文档的写法: ```java mRTASR.lang("msft"); mRTASR.OstAccent("mandarin"); mRTASR.OstDomain("ist_mul_msft"); mRTASR.setParams("language_name", "zh-CN"); ``` iOS 同样用 `RTASR(region: RegionMSFT)`,`language_name` 用下表。现在插件把界面语种直接写进 `engine.lang`,和上面的固定值不符,拼接落地时要改过来。 识别语种和这条路径的默认音色: | 界面语种 | 识别 `language_name` | 作为译文时的默认音色 | |---|---|---| | 普通话 `zh` | `zh-CN` | `zh-CN-XiaoxiaoNeural` | | 粤语简体 `yue` | `yue-CN` | `yue-CN-XiaoMinNeural` | | 粤语繁体 / 香港 `zh-HK` | `zh-HK` | `zh-HK-HiuMaanNeural` | | 爱尔兰语 `ga` | `ga-IE` | `ga-IE-OrlaNeural` | 另一端如果是微软同传表里的语言,识别用该语言的区域码(英语 `en-US`、日语 `ja-JP`),合成用 `OnlineTTS` 的区域码音色(英语 `en-US-JennyNeural`,对应同传表里的 `JennyNeural`)。不要用星火的 `x_John`、`x_Catherine`、`xiaoyan`。 现在同声的 `startListen` 在非爱尔兰语时走进 `ASR()`,`language=zh_cn`、`domain=iat`。那是星火听写。中文、粤语、爱尔兰语的拼接不准再进这个分支。 翻译是整句文本,方向仍固定为源 → 目标。中间结果只上屏,整句再翻译、再合成。 两端都不在微软同传表里、又不是中文、粤语、爱尔兰语:同声不启动,也不退回星火听写。 ## 改哪些地方 | 位置 | 改动 | |---|---| | `sparkchain` 插件 iOS / Android | 同传表内:新增 `AST(RegionMSFT)`,`use_tts` 和 `tts_speaker` 按上一节。表外三语:`RTASR` 按上面的四个固定参数加 `language_name` 启动;`OnlineTTS(RegionMSFT)` 用微软神经音色。同声路径不再创建 `ASR`,不再走 `ClassicTts` | | `sparkchain_session.dart` | 同声按语种对选一条:`startAst` 或 `startMsftListen`。`startListen` 里现在的星火 `ASR` 不给同声用 | | `translation_controller.dart` 同声分支 | 表内:PCM 写入 `AST`,译文用 `trans`,音频用 `tts`。表外三语:PCM 写入微软 `RTASR`,整句再翻译,再用 `OnlineTTS` 播目标语种。播放仍进现在的 `PcmStreamPlayer` | | 发音人 | 表内用同传短名;拼接用上表的 `xx-XX-NameNeural`。不要读 `getIflytekTTSLanguageSpecs` | `SparkChain.init` 的 `apiType` 仍按现有配置。`RegionMSFT` 是这一次会话的机房,不要为了同声把全局节点改掉。 ## 验收 - 日语 → 英语:一条 `AST`,`tts_speaker=JennyNeural`。没有 `ASR`,没有 `xiaoyan` / `tts-api.xfyun.cn`。 - 英语 → 日语:`tts_speaker=NanamiNeural`。两种方向的声音不同。 - 中文 → 英语:日志是 `RTASR`、`language_name=zh-CN`、`lang=msft`。译文用 `en-US-JennyNeural`。没有 `ASR`、没有 `zh_cn`、没有晓燕。 - 英语 → 中文:识别 `language_name=en-US`,播报 `zh-CN-XiaoxiaoNeural`。 - 中文 → 爱尔兰语:识别 `zh-CN`,播报 `ga-IE-OrlaNeural`。 - 粤语 → 英语:识别 `yue-CN` 或 `zh-HK`,对上用户选的简体或香港繁体。 - 连耳机时收音日志仍是「同声翻译收音:耳机麦」,译文从耳机出。