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))。上一课虚拟设备的识别部分使用SpeechConfig与SpeechRecognizer,源码可参考 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 requestsSpeechTranslationConfig与TranslationRecognizer用于语音翻译,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_config和recognizer声明整体替换为:
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,它按number与time 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):
- 打印原文,调用
translate_text得到用户语言译文; - 构造 SSML:
<speak>与<voice>标签的xml:lang使用用户语言language,声音名first_voice.short_name通过get_voices_async()按用户语言 locale 匹配得到(见 app.py); - 先
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 训练时提供的示例不完全一致。若定时器无法从翻译后的文本中解析出正确的时间,建议:
- 把实际出现的翻译句式作为新示例补充进 LUIS;
- 重新训练模型;
- 重新发布到
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),仅供参考