尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

IoT-For-Beginners 智能定时器实战:在虚拟 IoT 设备上用 Azure 语音服务实现文本转语音(TTS)

IoT-For-Beginners 智能定时器实战:在虚拟 IoT 设备上用 Azure 语音服务实现文本转语音(TTS) IoT-For-Beginners 智能定时器实战在虚拟 IoT 设备上用 Azure 语音服务实现文本转语音TTS【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners本篇指南聚焦 IoT-For-Beginners 第 6 部分「消费类物联网」第 3 课中的虚拟设备Virtual IoT Device方案讲解如何复用上一课用于语音识别的 Azure Speech 服务在smart-timer项目中通过SpeechSynthesizer将文本合成为语音让设备在定时器启动与结束两个时刻对用户进行语音播报。学完本篇你将掌握 Speech SDK 的语音合成配置、语音Voice动态选取、SSML 拼接以及「朗读期间暂停连续识别」这一关键防回声技巧并能读懂仓库中完整的可运行示例源码。为什么定时器需要文本转语音在 6-consumer/lessons/3-spoken-feedback/README.md 中本课将智能助手定义为双向通信设备用户对它说话set a 3 minute timer它也必须用语音回应Ok, your timer is set for 3 minutes。前两课已经完成了「语音→文本→LUIS 意图解析→获取定时秒数」的链路本课补上最后一块拼图——把确认信息与倒计时结束提醒用语音说出来。文本转语音Text to SpeechTTS的典型流程分为三个阶段文本分析把 1234 按语境转换为 one thousand two hundred thirty four 或 one two three four、语言分析拆分为音素并附加语调数据、波形生成早期系统拼接单音录音现代系统使用深度学习模型生成接近真人自然度的语音。你不需要自己实现这些阶段——Azure 语音服务的SpeechSynthesizer会替你完成全部工作设备只需把文本和语音参数发给云端服务即可拿回可直接播放的音频数据。虚拟设备方案的整体链路在虚拟 IoT 设备运行 Python 的 PC 上模拟中smart-timer的完整工作流如下可从 code-spoken-response/virtual-iot-device/smart-timer/app.py 一窥全貌SpeechRecognizer持续识别麦克风输入把语音转成文本process_text将文本 POST 到上一课构建的 serverless 函数text-to-timer函数内部调用 LUIS 解析set timer意图拿回定时秒数create_timer用threading.Timer创建后台定时线程秒数到达后触发announce_timersay函数调用SpeechSynthesizer.speak_ssml()朗读公告文本——这正是本文要实现的代码。下面按原文档的实操步骤从零编写这段 TTS 代码。前置条件已完成上一课第 2 课「语言理解」的smart-timer项目包含speech_api_key、location、language三个变量Speech 服务密钥、区域、语言代码并已实现基于SpeechRecognizer的连续语音识别虚拟环境已在 VS Code 终端中加载python -m venv .venv创建后需激活serverless 函数应用处于运行状态以便定时器秒数解析正常工作。步骤一导入 SpeechSynthesizer打开smart-timer项目中的app.py在现有from azure.cognitiveservices.speech import ...导入语句中加入SpeechSynthesizerfrom azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizerSpeechSynthesizer是 Speech SDK 中负责「文本/SSML → 音频」的核心类与SpeechRecognizer同属azure.cognitiveservices.speech包。步骤二为合成器创建语音配置在say函数上方创建一套独立于识别器的SpeechConfigspeech_config SpeechConfig(subscriptionspeech_api_key, regionlocation) speech_config.speech_synthesis_language language speech_synthesizer SpeechSynthesizer(speech_configspeech_config)这里复用了与识别器相同的 API 密钥、区域和语言但请注意两点差异识别器配置的是speech_recognition_language而合成器配置的是speech_synthesis_language二者语义不同、需分别设置由于调用get_voices_async()时会用到speech_synthesizer因此配置与实例化必须放在模块级脚本主流程中而不能放在每次调用的say函数内部否则会反复创建连接、拖慢响应。步骤三动态选取匹配语言的语音每种语言都支持多种语音Voice可通过 SDK 直接获取列表并挑选。在配置代码下方追加voices speech_synthesizer.get_voices_async().get().voices first_voice next(x for x in voices if x.locale.lower() language.lower()) speech_config.speech_synthesis_voice_name first_voice.short_name这段代码的工作机制是get_voices_async()异步拉取该 Speech 服务支持的全部语音列表.get()同步等待结果列表中的每个语音对象带有locale如hi-IN与short_name如hi-IN-SwaraNeural属性next(...)找到第一个locale与当前language忽略大小写匹配的语音把其short_name写入speech_synthesis_voice_name后续合成即使用该语音。备选方案硬编码指定语音如果你想固定使用某个特定发音人如带特定口音的语音可以删掉上述动态查找逻辑直接从语音支持文档中挑一个short_name硬编码speech_config.speech_synthesis_voice_name hi-IN-SwaraNeural步骤四为响应生成 SSMLsay函数需要向服务端发送的不是裸文本而是Speech Synthesis Markup LanguageSSML——一种基于 XML 的语音合成标记语言可声明文本语言、所用语音甚至可控制语速、音量、音调。更新say函数内容拼接 SSMLdef say(text): ssml fspeak version\1.0\ xml:lang\{language}\ ssml fvoice xml:lang\{language}\ name\{first_voice.short_name}\ ssml text ssml /voice ssml /speak生成的 SSML 结构与 6-consumer/lessons/3-spoken-feedback/README.md 中给出的示例一致例如使用英国英语语音en-GB-MiaNeural播报 Your 3 minute 5 second time has been set 时SSML 形如speak version1.0 xml:langen-GB voice xml:langen-GB nameen-GB-MiaNeural Your 3 minute 5 second time has been set /voice /speak步骤五朗读前暂停识别、朗读后恢复在 SSML 拼接代码下方执行「停识别 → 朗读 → 恢复识别」三段操作recognizer.stop_continuous_recognition() speech_synthesizer.speak_ssml(ssml) recognizer.start_continuous_recognition()这一步是整个方案中最容易被忽略却最关键的细节如果朗读期间麦克风识别仍在运行设备自己播报的语音会被SpeechRecognizer捕获、转成文本、发给 LUIS并被误判为一条「设置新定时器」的请求——于是新定时器触发新播报、新播报又被识别成新请求形成永不终止的无限循环。先stop_continuous_recognition()再朗读可以彻底切断这条回声路径。 想直观验证这一点把停止/恢复识别的两行注释掉然后设置一个定时器观察设备是否会因自己的播报而不断创建新定时器。步骤六运行与验证启动函数应用后运行虚拟设备程序对着麦克风说类似 set a two minute timer 的指令应当听到两次语音反馈定时器刚创建时——Your 2 minute timer started.确认已设置倒计时归零时——Times up on your 2 minute timer.提醒时间到。完整可运行的参考实现仓库在 code-spoken-response/virtual-iot-device/smart-timer/app.py 中提供了完整的成品代码上文各步骤均可在其中找到对应实现。其核心骨架如下import requests import threading import time from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizer speech_api_key key location location language language recognizer_config SpeechConfig(subscriptionspeech_api_key, regionlocation, speech_recognition_languagelanguage) recognizer SpeechRecognizer(speech_configrecognizer_config) def say(text): ssml fspeak version\1.0\ xml:lang\{language}\ ssml fvoice xml:lang\{language}\ name\{first_voice.short_name}\ ssml text ssml /voice ssml /speak recognizer.stop_continuous_recognition() speech_synthesizer.speak_ssml(ssml) recognizer.start_continuous_recognition() def announce_timer(minutes, seconds): announcement Times up on your if minutes 0: announcement f{minutes} minute if seconds 0: announcement f{seconds} second announcement timer. say(announcement) def create_timer(total_seconds): minutes, seconds divmod(total_seconds, 60) threading.Timer(total_seconds, announce_timer, args[minutes, seconds]).start() announcement if minutes 0: announcement f{minutes} minute if seconds 0: announcement f{seconds} second announcement timer started. say(announcement) def get_timer_time(text): url URL body {text: text} response requests.post(url, jsonbody) if response.status_code ! 200: return 0 payload response.json() return payload[seconds] def process_text(text): print(text) seconds get_timer_time(text) if seconds 0: create_timer(seconds) def recognized(args): process_text(args.result.text) recognizer.recognized.connect(recognized) recognizer.start_continuous_recognition() speech_config SpeechConfig(subscriptionspeech_api_key, regionlocation) speech_config.speech_synthesis_language language speech_synthesizer SpeechSynthesizer(speech_configspeech_config) voices speech_synthesizer.get_voices_async().get().voices first_voice next(x for x in voices if x.locale.lower() language.lower()) speech_config.speech_synthesis_voice_name first_voice.short_name while True: time.sleep(1)代码要点补充说明announce_timer与create_timer中的公告文本都会按时间单位是否有值决定是否拼入语句——分钟为 0 时只报秒数反之亦然避免出现 0 minute 这类冗余播报threading.Timer(total_seconds, announce_timer, args[minutes, seconds]).start()创建后台线程定时结束后自动调用announce_timer(minutes, seconds)不阻塞主循环while True: time.sleep(1)让主线程保持存活使识别回调与定时线程持续运行。函数应用侧的 TTS 对照实现如果你选用「设备端调用 serverless 函数获取音频」的架构而非直接在设备上合成仓库同样给出了函数应用示例位于 code-spoken-response/functions/smart-timer-triggertext-to-speech/init.py接收language、voice、text三个字段先用Ocp-Apim-Subscription-Key换取访问令牌再向https://{location}.tts.speech.microsoft.com/cognitiveservices/v1发送application/ssmlxml请求返回riff-48khz-16bit-mono-pcm格式音频get-voices/init.py调用语音列表端点按语言过滤后返回该语言下所有ShortName语音名列表——这与虚拟设备端get_voices_async()的职责对等local.settings.json定义了SPEECH_KEY、SPEECH_LOCATION、LUIS_KEY等环境变量占位符运行函数前需替换为真实值text-to-timer/init.py调用 LUIS 预测接口命中set timer意图时把number与time unit实体换算成总秒数返回。对比可见虚拟设备方案把语音合成能力放在设备端 Python 进程内依赖azure-cognitiveservices-speechSDK而函数方案把合成能力收拢到云端、设备只负责播放两种思路在本课的 ArduinoWio Terminal见 wio-terminal-text-to-speech.md与树莓派见 pi-text-to-speech.md等路径中也各有体现可按硬件能力与部署策略取舍。小结与进阶实验至此smart-timer已经具备完整的「语音设置定时器 → 语音确认 → 语音提醒」闭环。原文档在 README 的挑战环节还给出了一条进阶路线SSML 支持对指定词语添加强调、插入停顿、改变音调等控制标记你可以尝试从设备发送不同 SSML 并对比合成效果体会标记语言对发音细节的控制能力。参考路径速览虚拟设备成品代码code-spoken-response/virtual-iot-device/smart-timer/app.py本课总览6-consumer/lessons/3-spoken-feedback/README.md定时器设置步骤single-board-computer-set-timer.md函数应用 TTS 实现text-to-speech/init.py【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表