3分钟搞定讯飞云 TTS 语音合成:MicroPython+uPyPI一键安装驱动包

四、使用 websocket 连接讯飞开发平台实现 TTS 语音合成

原文链接:https://f1829ryac0m.feishu.cn/wiki/J0lDwNHtCizJwekOXRecPA7inwb?fromScene=spaceOverview

4.1 讯飞开发平台的介绍和 API Key 的获取

image.png

讯飞开放平台的​在线语音合成​​(TTS​​)服务​,是一款可将文字信息转化为自然流畅人声的 AI 能力,提供超 100 种特色发音人(音库)选择,支持多语种、多方言与中英混合输入,可灵活配置音频参数,广泛应用于新闻阅读、出行导航、智能硬件、通知播报等场景。

该服务核心提供 Websocket 流式 API 接口,相比传统 HTTP API 具备原生跨域优势,相比 SDK 更具轻量、跨语言特性,适配需要流式数据传输的 AI 服务场景;原 WebAPI 普通版接口已不再对外开放,存量用户可继续使用,平台也推荐开发者迁移至新版流式接口。

服务额外支持韩语、日语、维吾尔语、藏语等多类小语种及少数民族语言,使用时需采用 UTF-8 编码并在控制台开启对应发音人权限;用户可免费试用(默认每日 500 次免费调用额度),也可购买正式套餐,调用前需在控制台获取 AppID、APIKey、APISecret 等有效密钥,同时平台提供完整的 API 文档、多平台 SDK Demo 与技术支持,还配套有一句话复刻、超拟人语音合成、长文本语音合成、离线语音合成等衍生能力,覆盖多样化语音合成需求。

点击链接:https://www.xfyun.cn/services/online_tts

点击框选的「免费试用」按钮,是开启服务开通、获取 API 权限的第一步。

该页面为讯飞开放平台的免费服务申领页,新用户可在此领取在线语音合成的免费试用额度(2 万次交互量,有效期 3 个月)。点击框选的「立即领取」按钮,即可完成免费服务的申领,获得该服务的基础调用权限,为后续创建应用、获取密钥做准备。

进入控制台后,需创建专属应用来生成唯一的 API 凭证。

应用创建成功后,系统会自动匹配新用户免费套餐(在线语音合成,0 元,有效期 90 天,10000 次服务量)。确认套餐信息后即可完成服务开通,正式获得该应用的语音合成 API 调用资格。

完成服务开通后,点击页面右上角框选的「控制台」按钮,即可进入讯飞开放平台开发者后台,该后台是管理所有应用、查看服务用量、获取 API 密钥的核心操作入口。

在控制台「我的应用」页面,可查看所有已创建的应用。点击框选的「TTS 语音合成」应用,即可进入该应用的详情页,进一步获取语音合成服务的 API 密钥信息。

进入应用详情页后,在左侧功能栏中点击框选的「语音合成」菜单,即可展开语音合成相关的服务子选项,选择「在线语音合成」即可进入服务详情页,获取 API 认证信息。

在在线语音合成服务详情页,框选的「Websocket 服务接口认证信息」区域,可获取到调用 API 所需的全部核心凭证:​APPID、APIKey、APISecret​。这三个参数是调用在线语音合成流式 API 的必备密钥,完成此步骤即成功获取到 API 调用权限。

4.2 驱动库安装

upypi(https://upypi.net/)中搜索 xfyun_tts

这是一个适用于 MicroPython 的讯飞在线语音合成(TTS)驱动,通过 WebSocket 连接讯飞开放平台,将文字实时合成为 PCM 或 WAV 音频文件,已在树莓派 Pico 2W 上通过验证。

复制安装命令:

mpremote mip install https://upypi.net/pkgs/xfyun_tts/1.0.0

输入到终端中执行:

然后将下面代码中 WIFIAPI 相关配置项补全,烧录到单片机中:

# Python env   : MicroPython v1.23.0
# -*- coding: utf-8 -*-
# @Time    : 2026/04/12
# @Author  : leeqingsui
# @File    : main.py
# @Description : iFlytek TTS usage example for MicroPython on Raspberry Pi Pico 2W
# @License : MIT

# ======================================== 导入相关模块 =========================================

import network
import asyncio
import time
import ntptime
from xfyun_tts import XfyunTTS

# ======================================== 全局变量 ============================================

WIFI_SSID     = "your_wifi_ssid"
WIFI_PASSWORD = "your_wifi_password"

APPID      = "your_appid"
API_KEY    = "your_api_key"
API_SECRET = "your_api_secret"

OUTPUT_FILE = "output.pcm"
OUTPUT_WAV  = "output.wav"

# ======================================== 功能函数 ============================================

def connect_wifi():
    """
    连接 WiFi 并返回网络对象。

    Returns:
        network.WLAN: 已连接的 WLAN 对象;连接失败时返回 None。

    ==========================================

    Connect to WiFi and return the network object.

    Returns:
        network.WLAN: Connected WLAN object; None if connection fails.
    """
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)

    if not wlan.isconnected():
        print("Connecting to WiFi:", WIFI_SSID)
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)

        timeout = 15
        while not wlan.isconnected() and timeout > 0:
            time.sleep(1)
            timeout -= 1
            print("Connecting...", timeout, "s remaining")

        if wlan.isconnected():
            ip_info = wlan.ifconfig()
            print("WiFi connected")
            print("IP:", ip_info[0])
            print("Gateway:", ip_info[2])
        else:
            print("WiFi connection failed")
            return None
    else:
        print("WiFi already connected")

    return wlan


def sync_ntp():
    """
    通过 NTP 同步系统时间,为讯飞 API 鉴权签名提供准确时间戳。
    依次尝试多个 NTP 服务器,全部失败时打印警告但不中断流程。

    ==========================================

    Sync system time via NTP for iFlytek API authentication signature.
    Tries multiple NTP servers in order; prints a warning if all fail.
    """
    servers = ("ntp.aliyun.com", "ntp.tencent.com", "pool.ntp.org")
    for host in servers:
        try:
            ntptime.host = host
            ntptime.settime()
            t = time.gmtime()
            print("NTP synced via {}: {}-{:02d}-{:02d} {:02d}:{:02d}:{:02d} UTC".format(
                host, t[0], t[1], t[2], t[3], t[4], t[5]))
            return
        except Exception as e:
            print("NTP failed ({}):".format(host), e)
    print("NTP sync unavailable; signature timestamp may be rejected.")


async def run_tts(text):
    """
    调用 XfyunTTS 流式合成指定文本,直接将 PCM 数据写入本地文件。

    Args:
        text (str): 待合成的文本内容。

    ==========================================

    Synthesize the given text using XfyunTTS in streaming mode,
    writing PCM data directly to a local file.

    Args:
        text (str): Text to synthesize.
    """
    print("Synthesizing:", text)
    total = await tts.synthesize(text, filepath=OUTPUT_FILE)

    if total:
        print("Saved", total, "bytes ->", OUTPUT_FILE)
    else:
        print("Synthesis failed: no audio data received.")


async def run_tts_wav(text):
    """
    调用 XfyunTTS 流式合成指定文本,直接将带 WAV 头的音频写入本地文件。
    WAV 文件可在 PC 上直接用任意播放器打开,无需指定格式参数。

    Args:
        text (str): 待合成的文本内容。

    ==========================================

    Synthesize the given text using XfyunTTS in streaming mode,
    writing a WAV file (with header) directly to local storage.
    The WAV file can be opened on PC by any audio player without extra parameters.

    Args:
        text (str): Text to synthesize.
    """
    print("Synthesizing (WAV):", text)
    total = await tts.synthesize(text, filepath=OUTPUT_WAV)

    if total:
        print("Saved", total, "bytes PCM +44 bytes header ->", OUTPUT_WAV)
    else:
        print("Synthesis failed: no audio data received.")

# ======================================== 自定义类 ============================================

# ======================================== 初始化配置 ===========================================

tts = XfyunTTS(
    app_id     = APPID,
    api_key    = API_KEY,
    api_secret = API_SECRET,
)

# ========================================  主程序  ===========================================

if __name__ == "__main__":
    time.sleep(3)
    print("--- FreakStudio iFlytek TTS Demo ---")

    if not connect_wifi():
        print("Aborting: WiFi unavailable.")
    else:
        sync_ntp()

        # Demo 1: raw PCM output
        asyncio.run(run_tts("Hello, I am Xiaozhi. Nice to meet you."))

        # Demo 2: WAV output — open output.wav directly on PC to verify
        asyncio.run(run_tts_wav("Hi there, this is a WAV format test from Pico 2W."))

打开终端显示如下:

这是树莓派 Pico 2W 运行讯飞 TTS 程序的完整串口日志,完整呈现了两次语音合成的全链路流程:

  • 第一次合成文本 Hello, I am Xiaozhi. Nice to meet you.,累计接收 60158 字节音频数据,保存为 output.pcm
  • 第二次合成文本 Hi there, this is a WAV format test from Pico 2W.,累计接收 85332 字节数据,在 PCM 基础上添加 WAV 文件头,保存为 output.wav

日志完整验证了 WiFi 连接、NTP 时间同步、TTS 流式连接、音频分块接收、文件保存的全流程功能正常。

这是树莓派 Pico 2W 重启后的文件列表界面,框选的 output.pcmoutput.wav 是两次语音合成生成的最终音频文件,验证了程序在重启后仍能稳定生成并保存音频。

其中:

  • output.pcm 是无文件头的原始 ​PCM​ 裸数据;
  • output.wav 是添加了标准 WAV 文件头、可直接播放的通用音频格式。

这是将树莓派 Pico 生成的音频文件导出到 Windows 电脑后的文件列表,框选的 output.pcm(59KB,PCM 格式)和 output.wav(84KB,WAV 格式)是语音合成的最终产物。WAV 文件因包含 44 字节的标准文件头,体积略大于 PCM 文件,可直接在电脑端用普通播放器播放,PCM 文件则需专用工具播放或转换格式。

文件如下:

image.png
我们可以在网站:https://pcm.qer.im/中播放 PCM 音频文件:

这是在线 PCM 音频播放器(https://pcm.qer.im/)的文件选择界面,框选的 output.pcm 是从树莓派导出的原始音频文件。该工具解决了 PCM 文件无文件头、普通播放器无法直接播放的问题,可直接导入 PCM 文件,用于验证语音合成的音频内容。

通过在线工具 https://pcm.qer.im/,导入从树莓派导出的 output.pcm 文件,即可直接播放原始 PCM 音频,同时支持将 PCM 转换为 WAV、MP3 等通用格式,方便后续使用。

这是在线 PCM 播放器的参数配置区域,框选的采样率: 8000 Hz 是播放 output.pcm 的核心参数,需与讯飞 TTS API 返回的音频参数、树莓派程序的配置完全一致(配套参数为 16bit 位深度、单声道、小端序),才能正确解码并播放音频,还原语音合成的内容,是 PCM 文件正常播放的关键。

我们即可看到所有步骤完成。

原文链接:https://f1829ryac0m.feishu.cn/wiki/J0lDwNHtCizJwekOXRecPA7inwb?fromScene=spaceOverview

eb6b459ccb3f99726a2fd06d98170352.png

e56a916b375ed771aab3187baee81773.png

posted @ 2026-04-14 14:08  FreakStudio  阅读(9)  评论(0)    收藏  举报