基于 Azure Speech REST API 的 Raspberry Pi 语音转文本实现(IoT-For-Beginners smart-timer)
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
本指南来自 IoT-For-Beginners 项目第 6 部分「消费者设备」第 1 课(语音识别)的 Raspberry Pi 分支,讲解如何在树莓派上把录音按钮捕获到的语音通过 Azure 认知服务语音服务 REST API 实时转换为文本。读完本文,你将掌握访问令牌获取、REST 调用、RecognitionStatus/DisplayText响应解析,并得到一个可运行的「智能定时器」语音输入原型。
工作原理:先换令牌,再调 REST API
pi-speech-to-text.md采用的方案不是官方 Python SDK,而是纯 HTTP REST 调用:先用 API Key 从令牌签发端点换取短期访问令牌,再携带该令牌把 WAV 音频 POST 到识别端点。访问令牌有效期只有 10 分钟,因此代码每次识别前都应重新换取,保证令牌始终新鲜。
整个过程对应三个关键端点与两个阶段:
- 换令牌:
POST https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken,请求头携带Ocp-Apim-Subscription-Key; - 识别:
POST https://{location}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1,请求头携带Authorization: Bearer <token>与音频格式声明,请求体为 WAV 二进制数据。
前置条件:硬件与录音环境
本课建立在前两小节之上:pi-microphone.md(麦克风/扬声器配置)与pi-audio.md(按键控制录音)。需要确认:
- 硬件:麦克风(USB 麦克风、USB 声卡+3.5mm 麦克风,或 [ReSpeaker 2-Mics Pi HAT],注意蓝牙麦克风在 Pi 上兼容性差);Grove 按键(若使用 ReSpeaker HAT 则免接,HAT 自带按键在 D17);扬声器。
- 系统配置:用
arecord -l查麦克风卡号,用aplay -l查扬声器卡号(card 0: Headphones为板载 3.5mm 接口),并在/usr/share/alsa/alsa.conf中把defaults.pcm.card改成目标扬声器卡号。 - 依赖安装:
sudo apt update sudo apt install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev libasound2-plugins --yes pip3 install pyaudio - 录音代码:
app.py用 PyAudio 打开pyaudio.paInt16、单声道、rate=48000(如报Invalid sample rate改 44100 或 16000)、frames_per_buffer=4096的输入流,while button.is_pressed()循环把 4096 字节块写入frames,松键后用wave模块封装为内存 WAV(io.BytesIO)并返回。可参照 code-record/pi/smart-timer/app.py。
实现步骤:把录音变成文本
以 code-speech-to-text/pi/smart-timer/app.py 为最终形态,逐步改造smart-timer项目中的app.py:
1. 准备请求库与配置
删除上一节用于回放的play_audio函数(智能定时器不需要复读用户的话),并在文件顶部加入:
import requests在while True循环之前声明语音服务配置:
speech_api_key = '<key>' location = '<location>' language = '<language>'<key>:语音服务资源的 API Key(创建资源后由az cognitiveservices account keys list获取);<location>:创建资源时选择的区域,例如eastus,它决定令牌端点和识别端点的域名;<language>:语音区域设置(locale),如en-GB对应英语,zn-HK对应粤语。完整列表见微软官方「Language and voice support」文档。
2. 获取访问令牌
def get_access_token(): headers = { 'Ocp-Apim-Subscription-Key': speech_api_key } token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken' response = requests.post(token_endpoint, headers=headers) return str(response.text)该函数把 API Key 放进Ocp-Apim-Subscription-Key请求头,POST 到令牌签发端点,返回的响应体即访问令牌字符串。令牌有效期 10 分钟,若识别返回 401(令牌过期),需重新调用本函数换新令牌再重试——这一点在 Wio Terminal 的 C++ 实现中体现得更明显(见 wio-terminal-speech-to-text.md 的 401 分支处理)。
3. 声明识别函数并组装请求
def convert_speech_to_text(buffer): url = f'https://{location}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1' headers = { 'Authorization': 'Bearer ' + get_access_token(), 'Content-Type': f'audio/wav; codecs=audio/pcm; samplerate={rate}', 'Accept': 'application/json;text/xml' } params = { 'language': language }这里要点:
- URL 中的
{location}与配置一致,conversation表示会话式识别场景; Authorization使用Bearer前缀 + 令牌,每次调用都现场换取,保证不过期;Content-Type声明音频为 WAV/PCM,并携带samplerate={rate},该值与录音时 PyAudio 的采样率必须一致(源码里rate是全局变量,来自pi-audio.md的 48000/44100/16000);Accept声明接受 JSON 或 XML;params的language告诉服务音频属于哪种语言。
4. 发送音频并解析结果
response = requests.post(url, headers=headers, params=params, data=buffer) response_json = response.json() if response_json['RecognitionStatus'] == 'Success': return response_json['DisplayText'] else: return ''data=buffer直接上传上一节capture_audio()返回的 WAV 内存缓冲。响应 JSON 中:
RecognitionStatus:识别状态,Success表示成功提取出语音;DisplayText:识别出的文本(DisplayText对文本进行显示优化,例如去掉标点、数字格式化等)。
5. 处理文本并改写主循环
def process_text(text): print(text) while True: while not button.is_pressed(): time.sleep(.1) buffer = capture_audio() text = convert_speech_to_text(buffer) process_text(text)原循环中的play_audio(buffer)被替换为「识别 + 打印」。process_text目前只打印到控制台,在后续课程中会扩展为解析语音命令并设置定时器。
6. 运行验证
python3 app.py按下按键对着麦克风说话,松键后语音被转为文本打印:
pi@raspberrypi:~/smart-timer $ python3 app.py Hello world. Welcome to IoT for beginners.可尝试同音异义词句子,例如I want to buy two bananas and an apple too,观察服务如何依据上下文选择正确的 to/two/too,而非仅凭发音。
常见问题排查
OSError: [Errno -9997] Invalid sample rate:录音采样率不被硬件支持,将rate改为 44100 或 16000;- ALSA 提示
Unknown PCM cards.pcm.front等:来自 Pi 上未连接的音频设备配置,可忽略; - 识别返回 401:访问令牌过期,应重新调用
get_access_token()后重试; - 识别结果为空:检查
language是否与说话语言匹配、samplerate是否与录音一致、是否返回RecognitionStatus非Success(此时函数返回空字符串)。
与另外两条实现路径的对照
同一课还提供了另外两份对照实现,便于理解 REST 与 SDK 的差异:
- 虚拟设备(virtual-device-speech-to-text.md):在 PC 上使用官方 Python SDK
azure-cognitiveservices-speech,通过SpeechConfig+SpeechRecognizer连续监听,recognized回调输出文本,无需手动换令牌; - Wio Terminal(wio-terminal-speech-to-text.md):与 Pi 同样走 REST 路径,但需在
config.h内嵌两个 HTTPS 根证书(令牌端点证书与识别端点证书)、用WiFiClientSecure建立 TLS 连接,并通过自定义FlashStream(继承 ArduinoStream)把存放在 Flash 中的录音分块流式上传,避免内存溢出。FlashStream通过available()向HTTPClient报告可发送字节数、read()逐字节取数,超过HTTP_TCP_BUFFER_SIZE即重新填充缓冲。
Pi 与 Wio 都使用同一套 REST API 语义(Bearer 令牌、Content-Type采样率声明、DisplayText字段),区别仅在传输层的实现细节,这为理解语音服务的云端协议提供了很好的跨平台参照。
小结
至此,树莓派上的「按下说话、松键识别、控制台出文本」的语音转文本程序已可运行。你已掌握 Azure 语音服务的令牌机制、REST 调用格式、WAV/PCM 音频格式声明与响应解析,这些知识将直接支撑后续课程中「把识别文本转换为智能定时器命令」的实现。
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考