news 2026/9/17 1:23:04

IoT-For-Beginners 多语言支持实战:在虚拟 IoT 设备上用 Azure 语音翻译与 Translator 服务实现多语言智能定时器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
IoT-For-Beginners 多语言支持实战:在虚拟 IoT 设备上用 Azure 语音翻译与 Translator 服务实现多语言智能定时器

IoT-For-Beginners 多语言支持实战:在虚拟 IoT 设备上用 Azure 语音翻译与 Translator 服务实现多语言智能定时器

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

本指南基于 IoT-For-Beginners 课程第 24 课「Support multiple languages」中的虚拟设备实践章节,讲解如何把上一课仅支持单语的智能定时器升级为支持多语言交互:先用 Azure 语音服务(Speech service)把用户语音直接翻译成服务器语言文本并发送到 IoT Hub,再用 Translator 服务把服务器生成的应答文本翻译回用户语言并合成语音播放。读完本文,你将掌握SpeechTranslationConfig/TranslationRecognizer的多语种语音翻译用法,以及 Microsoft Translator REST API(v3.0)的完整调用流程,可直接在 虚拟设备完整源码 中落地验证。

背景:为什么智能定时器需要两级翻译

在前面三课中,你已经实现了语音转文本(Speech to text)、语言理解(LUIS)和文本转语音(Text to speech),但整套流水线都只围绕一种语言(通常是英语)工作:识别英语语音 → LUIS 理解英语 → 用英语 SSML 播报应答。要让定时器听懂并回应法语、粤语等其他语言,最务实的做法并非为每种语言重新训练 LUIS 模型,而是利用翻译能力把"用户侧语言"与"服务器侧语言"解耦:

  • 上行方向:用户说一种语言,语音服务在识别的同时直接把结果翻译成服务器语言(用于 LUIS 的英语),应用核心逻辑保持不变;
  • 下行方向:服务器用英语生成应答文本(如 "Times up on your 2 minute 27 second timer."),再通过 Translator 服务翻译回用户语言,最后用对应语言的声音合成播放。

课程 README.md 中的架构图直观展示了"日语输入 → 英语处理 → 日语应答"的翻译流程:

这种方案的价值在于:应用核心(LUIS 理解、定时逻辑、IoT Hub 消息)始终用服务器语言运行,通过翻译层快速为任意语言提供支持,后续再逐步演进为端到端母语支持。其代价是不同语言表达同一含义的方式不同,机器翻译结果可能与 LUIS 训练示例不完全一致,这点在 测试与调优 一节会专门讨论。

前期准备:从单语识别代码升级

本节实践以第 3 课(Spoken feedback)结束时的smart-timer项目为起点。在 VS Code 中打开该项目并确保虚拟环境已激活(终端提示符应显示(.venv))。上一课虚拟设备的识别部分使用SpeechConfigSpeechRecognizer,源码可参考 3-spoken-feedback 的虚拟设备代码:

recognizer_config = SpeechConfig(subscription=speech_api_key, region=location, speech_recognition_language=language) recognizer = SpeechRecognizer(speech_config=recognizer_config)

本课的核心改造正是把这段"单语识别"配置替换为"多语种翻译识别"。

第一步:用语音服务翻译用户语音

语音服务不仅能将语音转写成同语言文本,还能把识别输出直接翻译成其他语言。注意:翻译能力仅存在于 Speech SDK 中,REST API 并不内置翻译(README.md 对此有明确说明)。

1. 新增导入

app.py现有导入下方追加:

from azure.cognitiveservices import speech from azure.cognitiveservices.speech.translation import SpeechTranslationConfig, TranslationRecognizer import requests

SpeechTranslationConfigTranslationRecognizer用于语音翻译,requests库则在稍后调用 Translator REST API 时使用。完整源码的导入部分见 app.py。

2. 定义用户语言与服务器语言

智能定时器现在需要两个语言变量:language表示用户实际说话的语言(也是最终应答播报的语言),server_language表示训练 LUIS 所用语言(即服务器内部处理语言):

language = '<user language>' server_language = '<server language>'
  • <user language>替换为用户语言的语言标记(locale),例如法语fr-FR、粤语zh-HK
  • <server language>替换为训练 LUIS 时所用语言的 locale。

⚠️ 原文档给出的粤语示例写作zn-HK,这是笔误,正确的语言标记为zh-HK。支持语言的完整列表及其 locale 名称可查阅微软语音服务的语言与声音支持文档(Speech-to-text 一节)。

3. 用 SpeechTranslationConfig 替换 SpeechConfig

将上一课的recognizer_configrecognizer声明整体替换为:

translation_config = SpeechTranslationConfig(subscription=speech_api_key, region=location, speech_recognition_language=language, target_languages=(language, server_language)) recognizer = TranslationRecognizer(translation_config=translation_config)

这段代码创建了一个翻译配置:以用户语言language作为识别语言,同时要求输出用户语言与服务器语言两种翻译;随后用该配置创建TranslationRecognizer——一种可以把语音识别结果翻译成多种语言的识别器。

💁 关键细节:target_languages必须包含原始语言(即speech_recognition_language),否则不会产生任何翻译结果。这是因为返回的translations字典始终同时包含"原文"与"译文"条目,原文语言也需要一个键位来存放。

4. 改写 recognized 事件处理器

recognized函数整体内容替换为:

if args.result.reason == speech.ResultReason.TranslatedSpeech: language_match = next(l for l in args.result.translations if server_language.lower().startswith(l.lower())) text = args.result.translations[language_match] if (len(text) > 0): print(f'Translated text: {text}') message = Message(json.dumps({ 'speech': text })) device_client.send_message(message)

逻辑要点:

  • recognized事件并非只在"翻译成功"时触发,它也可能在语音被识别但未翻译时触发,因此先用args.result.reason == speech.ResultReason.TranslatedSpeech判断本次事件确实是"语音被翻译";
  • args.result.translations是一个字典,通过next(...)找到与服务器语言匹配的条目。注意:字典的键是locale 的语言部分而非完整 locale——例如请求翻译到fr-FR时,字典键是fr而不是fr-FR,所以匹配逻辑使用server_language.lower().startswith(l.lower())这种前缀匹配;
  • 取到非空译文后打印,并封装为Message通过device_client.send_message(message)发送到 IoT Hub,供 Functions 应用里的text-to-timer函数做 LUIS 意图解析(该函数实现见 text-to-timer/init.py,它按numbertime unit实体计算总秒数)。

5. 运行测试

确保 Functions 应用正在运行,然后用用户语言说出定时请求(自己说该语言,或用翻译 App 播放译文)。预期输出:

(.venv) ➜ smart-timer python app.py Connecting Connected Translated text: Set a timer of 2 minutes and 27 seconds.

至此,上行链路(用户语言 → 服务器语言文本 → IoT Hub)已经打通。注意本课完整代码中recognizer.recognized.connect(recognized)recognizer.start_continuous_recognition()的接线方式与上一课完全一致(见 app.py)。

第二步:用 Translator 服务把应答文本翻译回用户语言

语音服务只支持"语音 → 多语言文本",不支持把文本翻译回语音。因此下行链路需要借助独立的 Translator 服务——它提供文本翻译的 REST API,并且除翻译外还支持脏话过滤、术语自定义等扩展能力(见 README.md)。

若你尚未创建 Translator 资源,可参照 README.md 的创建命令:az cognitiveservices account create --name smart-timer-translator --resource-group smart-timer --kind TextTranslation --sku F0 --yes --location <location>,随后用az cognitiveservices account keys list取回密钥。

1. 添加 Translator API 密钥

speech_api_key下方新增:

translator_api_key = '<key>'

<key>替换为 Translator 资源的 API 密钥。

2. 定义 translate_text 函数

say函数上方定义translate_text(text),把文本从服务器语言翻译到用户语言。完整实现见 app.py,分三部分讲解。

定义 URL 与请求头:

url = f'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0' headers = { 'Ocp-Apim-Subscription-Key': translator_api_key, 'Ocp-Apim-Subscription-Region': location, 'Content-type': 'application/json' }

两个关键点:

  • 该 API 的 URL 不区分区域,区域信息通过请求头Ocp-Apim-Subscription-Region传递;
  • 与语音服务不同,Translator 直接使用 API 密钥(Ocp-Apim-Subscription-Key),无需先从 token 签发 API 换取访问令牌——对比 text-to-speech 函数 中语音 TTS 需要get_access_token()sts/v1.0/issuetoken的做法,可见两者鉴权机制差异。

定义查询参数与请求体:

params = { 'from': server_language, 'to': language } body = [{ 'text' : text }]
  • params声明源语言(from)与目标语言(to),本次调用把服务器语言翻译为用户语言;
  • body数组,因为单次调用可以翻译多段文本,每段是一个{'text': ...}对象。

发起请求并解析响应:

response = requests.post(url, headers=headers, params=params, json=body) return response.json()[0]['translations'][0]['text']

返回的响应是一个 JSON 数组,其中每个元素对应body中的一段文本,内部translations数组存放各目标语言译文。单段文本、单一目标语言时的典型响应:

[ { "translations": [ { "text": "Chronométrant votre minuterie de 2 minutes 27 secondes.", "to": "fr" } ] } ]

因此response.json()[0]['translations'][0]['text']取的就是第一段文本的第一条译文的text字段。作为对照,仓库中 Functions 应用的 translate-text 函数 使用完全相同的 URL、请求头、参数与响应解析逻辑,只是把from_language/to_language从 HTTP 请求体动态读取——可见这套 REST 调用模式在该课程里被设备端与云端一致复用。

3. 改造 say 函数

在生成 SSML 之前先翻译待播报文本,并打印原文与译文便于调试:

print('Original:', text) text = translate_text(text) print('Translated:', text)

改造后的say函数流程(完整实现见 app.py):

  1. 打印原文,调用translate_text得到用户语言译文;
  2. 构造 SSML:<speak><voice>标签的xml:lang使用用户语言language,声音名first_voice.short_name通过get_voices_async()按用户语言 locale 匹配得到(见 app.py);
  3. recognizer.stop_continuous_recognition()暂停识别,避免设备播报声音被自己的麦克风再次识别成指令,speech_synthesizer.speak_ssml(ssml)播放完成后立即start_continuous_recognition()恢复监听。

第三步:端到端运行与测试

确保 Functions 应用运行,用用户语言请求一个定时器。完整运行输出:

(.venv) ➜ smart-timer python app.py Connecting Connected Translated text: Set a timer of 2 minutes and 27 seconds. Original: 2 minute 27 second timer started. Translated: 2 minute 27 seconde minute a commencé. Original: Times up on your 2 minute 27 second timer. Translated: Chronométrant votre minuterie de 2 minutes 27 secondes.

其中上行(Translated text)来自语音服务的翻译识别,下行(Original/Translated两行)来自say函数内的 Translator 调用。需要指出的是,法语译文"2 minute 27 seconde minute a commencé"与母语者的自然表达仍有差距,这正是机器翻译的典型表现——不影响理解,但不够地道。

测试与调优:语义差异处理

不同语言表达同一含义的方式往往不同(例如法语中"我叫 Jim"直译是"Je m'appelle Jim"——字面为"我称呼我自己为 Jim",语序和用词都不同于英语),因此翻译结果很可能与 LUIS 训练时提供的示例不完全一致。若定时器无法从翻译后的文本中解析出正确的时间,建议:

  1. 把实际出现的翻译句式作为新示例补充进 LUIS;
  2. 重新训练模型;
  3. 重新发布到Staging槽位(对应 text-to-timer 函数 中get_slot_prediction请求的发布槽)。

多语言设备实操提示

如果你不会第二种语言,可以用 Bing Translate 或 Google Translate 把句子翻译成目标语言,再借助"听译文"功能把译文播放给麦克风。注意语音识别器可能会忽略设备自身播放的部分声音,必要时需用另一台设备播放译文:

从本课到"万能翻译器"作业

本课是 6-consumer 项目的最后一课。完成实践后,作业说明 要求你基于本课学到的语音识别、LUIS、语音合成与翻译能力,用两台 IoT 设备搭建一个"万能翻译器":每台设备各配置一种语言,一台设备把语音转成文本发送给对方,对方设备翻译后用目标语言语音播放。作业提示指出,设备间传递语音文本时应同时携带语言信息以简化翻译,也可先用 IoT Hub 与 Functions 应用注册设备并把语言存入 Azure Storage。

由于这是本项目的最后一课,完成作业后应参照 clean-up.md 清理云资源(请先完成作业再清理,作业运行期间需要这些服务)。

小结

本文完整复现了虚拟 IoT 设备的多语言改造路径:用SpeechTranslationConfig+TranslationRecognizer把用户语音实时翻译为服务器语言并发送到 IoT Hub,用 Translator REST API v3.0 把服务器应答文本翻译回用户语言,最终以用户语言合成语音播报。两个方向的关键实现证据分别位于 虚拟设备完整源码(语音翻译 + 文本翻译 + SSML 合成)与 translate-text 云函数(云端侧相同 REST 调用的镜像实现)。掌握了这套"识别语言 A → 处理语言 B → 播报语言 A"的翻译架构,你便可以为任意 IoT 应用快速叠加多语言能力。

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 1:21:29

STM32输入捕获+FFT联合测频实战:高精度实时频谱分析方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 1:21:28

/learn命令详解:用everything-claude-code从会话中提炼可复用模式

/learn命令详解&#xff1a;用everything-claude-code从会话中提炼可复用模式 【免费下载链接】everything-claude-code Claude Code toolkit - agents, commands, skills, rules, and hooks for productive AI-assisted development 项目地址: https://gitcode.com/GitHub_T…

作者头像 李华
网站建设 2026/9/17 1:18:45

512分辨率万能遮罩模型:局部重绘高精度实战指南

做AI图像后期和局部重绘这几年&#xff0c;最磨人的永远不是模型多难跑&#xff0c;而是“遮罩”这件事本身。尤其是当你只想改动画面里的某一块——换个表情、重绘一块背景、修掉反光——结果生成出来的边缘又硬又脏&#xff0c;或者干脆整个区域都跟原图脱节。512分辨率万能遮…

作者头像 李华