Skip to main content Link Menu Expand (external link) Document Search Copy Copied

AI聊天盒子 - 集成文字转语音功能

前言

上一篇文章我们集成了语音服务,我们可以通过语音向LLM提问,但是LLM的回答还是只能打印在运行日志里面。这篇文章我们来探索一下如何将LLM的应答转换成语音播放出来,实现完全的语音交互。为了实现这个目的,我们需要集成文字转语音服务,另外需要音频放大模块和小喇叭。

本系列其他文章

  1. AI聊天盒子 - 概念设计
  2. AI聊天盒子 - 使用esp-sr和Rust语言编写语音识别程序
  3. AI聊天盒子 - 请AI帮我编写和AI聊天的Rust代码
  4. AI聊天盒子 - 集成语音转文字服务

文字转语音

要实现“用户语音提问,LLM语音回答”,我们需要将LLM的回答转换成语音。乐鑫的esp-sr模块包含了TTS语音合成模型,可以不用联网就实现文字转语音功能。因为我们在第二篇文章中已经添加过esp-sr模块,我们只需在esp_sr_binding.h文件最后增加下面两行,使得Rust可以访问TTS头文件中的C接口。

...
#include "esp_tts.h"
#include "esp_tts_voice_template.h"

TTS语音合成模型实现文字转语音还需要用到声音模型。声音模型文件位于下列目录中,有几种模型可供选择,用户可以根据效果选用。

(ESP-RS) user1@blackbox:~/code/ai-chatbox$ find ./ -name "*.dat"
./target/xtensa-esp32s3-espidf/debug/build/esp-idf-sys-ac7343841da20c9c/out/managed_components/espressif__esp-sr/esp-tts/esp_tts_chinese/esp_tts_voice_data_xiaoxin_small.dat
./target/xtensa-esp32s3-espidf/debug/build/esp-idf-sys-ac7343841da20c9c/out/managed_components/espressif__esp-sr/esp-tts/esp_tts_chinese/esp_tts_voice_data_xiaole.dat
./target/xtensa-esp32s3-espidf/debug/build/esp-idf-sys-ac7343841da20c9c/out/managed_components/espressif__esp-sr/esp-tts/esp_tts_chinese/esp_tts_voice_data_xiaoxin_custom.dat
./target/xtensa-esp32s3-espidf/debug/build/esp-idf-sys-ac7343841da20c9c/out/managed_components/espressif__esp-sr/esp-tts/esp_tts_chinese/esp_tts_voice_data_xiaoxin.dat

为了存放声音模型,我增加了一个名为voice_data的新分区,更新后的partitions.csv如下。由于固件上传命令只会刷写程序,我在项目中增加了脚本upload-voice-data.sh用于将声音模型写到新分区中。

# Espressif ESP32 Partition Table
# Name,  Type, SubType, Offset,  Size
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory, app,  factory, 0x010000, 4M
voice_data, data,  fat, 0x410000, 3890K

另外介于在Rust代码中直接使用C接口有点繁琐,所以我们封装了TtsEngine对象,将C语言函数式的接口包装成Rust对象。具体的代码在tts.rs文件中可以找到,有了TtsEngine对象之后,我们只要调用TtsEngine的synthesize_and_play方法就可以将输入字符串转成语音。

外放电路

外放电路使用了一个基于MAX98357芯片的放大器模块和一个3W的小喇叭,模块加喇叭一套不到10元。

img

模块和ESP32S3的连接方式如下。左边是ESP32S3上的管脚,右边是放大器模块的管脚。

  1. GPIO1 <–> LRC
  2. GPIO2 <–> BCLK
  3. GPIO3 <–> DIN
  4. GPIO5 <–> SD
  5. 3V3 <–> VIN
  6. GND <–> GND

另外放大器模块还有一个控制增益的管脚GAIN,直接接GND时增益是12dB,接VDD时增益为6dB,悬空为9dB。连接好接口后整个系统如下图。

img

系统测试

先使用命令 env LLM_AUTH_TOKEN=<sdk_token> WIFI_SSID=<your_ssid> WIFI_PASS="password" VOS_URL="<vos_service_url>" cargo espflash flash -p /dev/ttyACM0 --flash-size 8mb 编译代码。VOS_URL是语音转文字服务的地址。再使用 upload-voice-data.sh /dev/ttyACM0 命令刷写语音模型。使用 cargo espflash monitor -p /dev/ttyACM0 命令查看日志,了解运行状态。

我问了LLM一个问题,回答最后以音频播放了出来。程序当前还有点问题,比如播放的回答的时候,录音并没有停止;另外麦克风的拾音效果比较一般,声音有点小,怪不得ESP-BOX使用了一堆麦克风。

点我观看

总结

本文给ai-chatbox增加了将LLM的解答转换成音频的功能。esp-rs自带的TTS声音效果一般,但是考虑ESP32S3的身材,勉强还能接受。希望乐鑫能发布更逼真一点的声音模型,最好是中英文兼容的声音模型。

链接

  1. ai-chatbox - https://github.com/paul356/ai-chatbox
  2. TTS语音合成模型 - https://docs.espressif.com/projects/esp-sr/zh_CN/latest/esp32s3/speech_synthesis/readme.html