HarmonyOS6.1.1-AI字幕:切换语言时-如何判断问题在组件状态还是翻译结果
我给 AI 字幕页加了“中文到英文”和“英文到中文”两个按钮后第一次演示的场面有点尴尬按钮颜色切过去了页面也写着新的语言方向可屏幕上没有一行新的英文或中文字幕。旁边的人问我语言切换是不是没有生效。我当时差点顺着这个问题去找翻译质量、语言包或者组件内部行为。回头看这个方向一开始就错了。当前页面能确认的是配置有没有更新不能从没有出现字幕文本反推出“翻译没工作”。真实字幕文本还依赖组件准备、麦克风授权、真实 PCM 输入以及设备上的系统能力。它们没有同时满足时页面静止是正常的不是语言按钮的反证。这篇只复盘这一个误判为什么我已经把语言方向切成en-US - zh-CN却仍不能把“字幕看起来没变”写成语言设置失效更不能把它写成翻译结果错误。故障现场两个状态都变了文本仍为空页面初始值是zh-CN到en-US修订号从 1 开始。点击“英文到中文”时按钮会变成选中颜色顶部显示也会改成en-US - zh-CN。我最初把这几个现象都当作“字幕应该立刻换语言”的前提忽略了它们只是配置层的状态。实际更新函数非常短它没有写入任何字幕文字也没有承诺产生翻译内容。它做的是保存新的源语言与目标语言再递增configRevision。这个修订号很有价值因为它给一次配置变化留下了可观察的编号而不是只靠肉眼看按钮颜色。private updateLanguage(sourceLanguage: string, targetLanguage: string): void { this.sourceLanguage sourceLanguage; this.targetLanguage targetLanguage; this.configRevision 1; }我在排查时先固定了一次操作记录切换前的方向和修订号点击一次再记录切换后的值。只要sourceLanguage、targetLanguage和修订号三者一致变化就能证明页面已提交了新的组件选项。至于屏幕上是否出现文字是下一段输入路径的事情不能抢在前面下结论。否是点击 英文到中文updateLanguagesourceLanguage 更新为 en-UStargetLanguage 更新为 zh-CNconfigRevision 加一组件 options 读取最新配置页面可核对本次配置组件已准备且有真实 PCM 输入没有新的字幕文本文本由真实组件运行时决定这个流程图把当时混在一起的两件事拆开了。语言设置是否写入落在 A 到 G文本能否出现取决于 H 之后。前者是当前代码可以直接观察的页面行为后者不能靠按钮点击替代。我最先查错的地方第一轮我盯的是字幕区域。它没有显示新语言文字我就怀疑sourceLanguage和targetLanguage没有传给组件。实际上页面通过buildOptions()每次构造AICaptionOptions把当前两个字段交给AICaptionComponent。这说明选项来源不是写死的默认值。private buildOptions(): AICaptionOptions { return { onPrepared: () { /* 只记录组件准备状态 */ }, onError: (error: BusinessError) { /* 只记录组件错误状态 */ }, sourceLanguage: this.sourceLanguage, targetLanguage: this.targetLanguage, fontSize: this.captionFontSize, fontColor: this.captionFontColor }; }第二轮我又把“组件没有显示文本”理解成“组件没有收到新配置”。这也不够严谨。组件的onPrepared和onError在页面里分别写入runtimeState它们说明的是组件准备或报错的运行时状态它们不是语言识别、翻译成功的回执。即使页面显示prepared仍然只说明组件可以进入后续输入流程不能凭空产生一段可当作结果的字幕。第三轮才回到正确顺序先核对配置修订号再核对组件状态随后才看麦克风和 PCM 输入。这样一来“没看到文本”不再是一个模糊结论而是能定位到某一段尚未发生的流程。为什么修订号比按钮颜色可靠按钮颜色是一个便利提示但它不能告诉我这是不是一次新的配置提交。比如用户先选“中文到英文”再重复点击同一按钮颜色没有变化若我只截按钮无法区分是没有操作还是重复操作。configRevision则提供了一个单调递增的操作标识。我把检查动作收紧成三步先读取当前sourceLanguage - targetLanguage和 revision点击目标组合再确认方向与 revision 是否符合预期。这里不需要制造一段测试音频也不需要猜测翻译文本。页面本身已经有足够的信息证明“配置变了”。运行时摘要AICaptionOptions页面状态操作者运行时摘要AICaptionOptions页面状态操作者未收到真实输入时不显示文本也不代表配置失败点击语言组合更新 source/target 与 revision按当前字段构造选项保持 prepared/error、PCM 状态独立这张图对应我后来使用的测试顺序。语言配置与运行时摘要并列展示而不是让字幕区域承担所有判断。这样页面出现“等待 AICaptionComponent onPrepared”时我知道该先解决准备状态页面出现“麦克风未授权未启动”时我知道该处理授权writeAudio次数为 0 时我知道没有真实 PCM 写入。没有哪一项可以被“字幕文字没变”替代。把误判改成可以落地的排查我后来给自己留了一张很短的排查表。第一项是语言值切换后是否确实从zh-CN - en-US变为en-US - zh-CN。第二项是 revision是否加一。第三项是组件状态waiting、prepared、failed不能混为一谈。第四项才是输入状态例如麦克风是否已授予、PCM 是否正在写入。这四项有先后不是因为某项更重要而是每项能回答的问题不同。语言值回答“我让组件采用哪种配置”revision 回答“这次操作是否真的提交”组件状态回答“组件是否准备好”PCM 计数回答“是否存在真实音频供组件处理”。只有最后一个问题向前推进字幕区才可能出现真实文本。有一次我为了让页面“看起来完整”想在切换语言后写一行“已切换为英文字幕”。这会让演示顺滑却会让状态含义失真。它把配置确认伪装成了文本结果也会让后续排查无法判断这行文字来自系统组件还是页面自己拼出来的。最后我没有加这种提示而是把“按钮只更新组件选项不生成识别或翻译结果”的边界保留在页面里。修复落点不在字幕文案而在状态分层这次并没有给语言切换函数补一个“翻译”调用。正确的调整是让每一层在页面上都有独立位置语言组合和修订号属于配置区onPrepared、onError属于组件状态麦克风授权、PCM 输入状态和writeAudio次数属于音频输入区。任何一层缺失都应如实显示缺失而不是借用字幕文案掩盖。当真实麦克风开始工作时回调才会把 PCM 数据交给控制器并增加写入次数。这个计数可以证明页面确实在向组件提供实时输入它仍不能说明识别内容或翻译内容正确。private readonly audioDataCallback (buffer: ArrayBuffer): void { try { this.captionController.writeAudio({ data: new Uint8Array(buffer) }); this.pcmWriteCount 1; this.audioInputState 正在从真实麦克风写入 PCM; } catch (error) { this.audioInputState PCM 写入失败; } };我特别保留了“真实”这个限定。因为模拟一个递增的数字很容易但那只能证明页面能改状态不能证明音频路径存在。这里的计数应当和麦克风授权、音频采集器启动以及实际回调一起看不能独立当成字幕结果。我会怎样复测复测第一组只做语言配置从中文到英文切到英文到中文记录两次方向和 revision。预期是方向对应按钮修订号各增加一次不要求字幕区域出现任何固定句子。第二组只做组件准备在不启动麦克风时观察waiting、prepared或failed。预期是页面只报告真实回调状态不用“已翻译”填补空白。第三组才在已准备且已授权的设备上启动真实麦克风观察 PCM 状态、写入次数和最后写入时间。即便此时有字幕显示我也只把它作为真实设备上的观察记录本篇不对语言识别准确率、翻译质量或文本内容作结论。这次复盘让我改掉了一个习惯看到屏幕没有变化时先不要问“结果为什么不对”而是逐层问“我到底改变了什么、组件已经准备到哪里、真实输入是否存在”。语言按钮能做的事情很明确超过它的范围就不该由它背锅。一次没有声音的复现让我看清了误判为了把问题从主观感受里拿出来我做了一次刻意安静的复现。设备放在桌面上既不申请麦克风权限也不点击启动 PCM 输入。此时字幕区没有任何文字运行时摘要中的输入状态也保持“未启动”。我先记下初始配置zh-CN - en-US、修订号 1。随后点击“英文到中文”配置区显示为en-US - zh-CN修订号变为 2按钮选中态也变化。这次复现非常有用因为我从头到尾没有制造“应该听到一句话”的期待。没有音频进入页面没有文本本来就符合条件但配置值和修订号发生变化说明语言操作已经完成。以前我会把这两件事压缩为一句“切换后没效果”现在会记录成两个独立事实配置已更新真实文本尚无输入条件不作判断。然后我反过来再做一遍不修改语言方向只重复打开页面、观察运行时状态。这时如果onPrepared尚未回调摘要会写 waiting如果回调失败会写 failed 和错误信息。无论是哪种情况revision 都不会自动变化。这个反向操作让我确认revision 是用户配置的操作记录不是组件健康度指标。把它当成“组件已重新准备”的证据同样会走偏。我还特别注意到语言按钮的按钮色只依据sourceLanguage是否匹配某一个值。也就是说它表达的是当前页面选择不是“上一次音频已经按该语言处理”。当语言方向为中文到英文时按钮高亮切成英文到中文另一颗按钮高亮。这个视觉反馈足够服务选择操作却不应承载运行时结论。不能用静态文案补足缺失的结果排查期间有人建议在切换语言后在页面下方显示“目标语言中文”或“目标语言英文”让用户能立刻感到变化。作为配置提示这没有问题问题在于提示很容易在后续迭代中被写成“中文字幕已开启”或“英文翻译已开启”。前者仍可理解为展示偏好后者已经暗示输出存在。我最终采用的判断方式是任何一句能被读成“系统已经说出了什么”的文案都不能由语言按钮单独产生。配置区只陈述sourceLanguage、targetLanguage和修订号运行时区只陈述waiting/prepared/failed、回调次数与时间输入区只陈述麦克风和 PCM。这样即使页面暂时空白用户也能从状态中理解哪里没有推进而不是把空白归因到翻译。这点在自动化测试时尤其重要。如果测试脚本只点击语言按钮再截图字幕区域结果会极不稳定有的设备没有输入有的设备未准备有的环境不能使用相关能力。反过来断言两个语言字段和 revision 则不依赖外界声音也不要求任何系统回调。把可控断言放在配置层把真机观察保留给运行时层测试报告就不会把环境差异写成代码失败。处理快速切换时我只相信最后一次配置还有一个小场景让我重新审视 revision。连续点“中文到英文”“英文到中文”“中文到英文”时用户真正关心的是当前停在哪一种方向而不是中间每次点击有没有让字幕立刻闪一下。页面状态会保留最后一次 source/target 组合修订号则把三次配置写成连续的变化。我没有试图根据 revision 推测每一次旧配置是否都被组件完整处理。那需要真实的组件回调与输入时序而当前页面没有为此提供文本级记录。revision 的职责更单纯帮助排查者确认最后一次配置不是旧值。若问题发生在连续点击之后先记录最终方向与最后 revision再观察组件是否准备而不是拿先前的屏幕印象去判断。这个原则也避免了另一个错误把 configRevision 增加解释成“语言包重新加载成功”。代码中它只是数字递增没有下载、加载或结果回调相关逻辑。写复盘时把它描述为配置版本比使用带有运行意味的词准确得多。按层次记录排查才不会绕回原点我现在会把一次问题记录写成四行。第一行是操作例如“点选英文到中文”第二行是配置例如“sourceen-UStargetzh-CNrevision4”第三行是组件摘要例如“preparedCount0状态 waiting”第四行是输入摘要例如“麦克风未请求writeAudio0”。四行都来自页面已有字段没有任何一行替代另一行。一旦未来真机上出现字幕记录方式也不需要改变。只是在第四行之后补充“观察到组件可见内容”并把内容是否与目标语言一致留给专门的真实设备测试。这样不会因一次成功观察倒过来弱化此前的边界更不会让一张截图承担配置、输入和文本质量三种不同结论。在这个页面里空白不是一个可以被随手填掉的缺陷描述。它可能是开关关闭、组件等待、权限未授予、采集未启动或仅仅是环境没有声音。把语言状态单独立起来后我能更早停止无效排查也能更诚实地说明本次到底看到了什么。防回归检查每次语言切换后同时核对sourceLanguage、targetLanguage和configRevision不只看按钮颜色。将prepared/error与麦克风、PCM 写入状态分开显示避免把组件状态当成字幕结果。未取得真实输入与组件回调时页面和稿件都不描述已生成、已翻译或准确的字幕文本。