AI Agent项目实战(03)-利用TTS技术让你的AI Agent发声

news2024/12/25 9:13:29

1 语音逻辑设计

一个AI Agent应用的语音逻辑设计流程图。

1.1 基本流程

- 用户 -> Agent -> 文本回答

最基础的交互模式。用户输入被传递给Agent,Agent生成文本回答。

1.2 添加语音功能

- 用户 -> Agent -> 文本回答
           |
           v
        TTS服务 -> MSTTS -> 语音回答

基本流程基础上,增加文本转语音(TTS)服务。Agent生成的文本回答被发送到TTS服务,然后通过MSTTS(Microsoft Text-to-Speech)转换为语音回答。

1.3 完整流程

- 用户 -> Agent -> 文本回答
           |
           v (异步)
        TTS服务 -> MSTTS -> 语音回答

文本回答和语音回答是并行处理的。Agent生成文本回答后,同时开始TTS转换过程,这个过程被标记为"异步"。

1.4 设计思路

  • 模块化:将文本处理和语音转换分离,便于独立开发和维护。
  • 异步处理:文本回答可以立即呈现,而语音转换在后台进行,提高响应速度。
  • 灵活性:可以根据需求选择只使用文本回答或同时使用语音回答。
  • 技术整合:利用MSTTS等成熟技术,提高语音质量。

这种设计允许AI Agent应用在保持高效文本交互的同时,提供更丰富的语音交互体验。

2 TTS能力介绍

以 Google Cloud Text-To-Speech 服务为例说明。

开发人员可用 Text-to-Speech 创建可播放音频格式的自然发音的合成人类语音。可用由 Text-to-Speech 创建的音频数据文件来丰富应用功能或者扩大视频或录音等媒体。

Text-to-Speech 会将文本或语音合成标记语言 (SSML) 输入转换为音频数据,例如 MP3 或 LINEAR16(WAV 文件中使用的编码)。

2.1 基本示例

Text-to-Speech 适用于向用户播放人类语音音频的任何应用。您可以使用它将任意字符串、字词和句子转换为表述相同内容的人的语音。

设想您有一个语音辅助应用,可以通过可播放音频文件,向您的用户提供自然语言反馈。您的应用可能会执行某个操作,然后向用户提供人类语音作为反馈。

例如,您的应用可能想要报告它已成功将某项活动添加到用户的日历中。您的应用会构建一个响应字符串向用户报告操作已成功,例如“我已将活动添加到您的日历中”。

使用 Text-to-Speech,您可以将该响应字符串转换为实际的人类语音以播放给用户,类似于下面提供的示例。

示例 1:Text-to-Speech 生成的音频文件

要创建音频文件,请向 Text-to-Speech 发送请求,如:

curl -H "Authorization: Bearer "$(gcloud auth print-access-token) -H "x-goog-user-project: <var>PROJECT_ID</var>" -H "Content-Type: application/json; charset=utf-8" --data "{
  'input':{
    'text':'I\'ve added the event to your calendar.'
  },
  'voice':{
    'languageCode':'en-gb',
    'name':'en-GB-Standard-A',
    'ssmlGender':'FEMALE'
  },
  'audioConfig':{
    'audioEncoding':'MP3'
  }
}" "https://texttospeech.googleapis.com/v1/text:synthesize"

2.2 语音合成

将文本输入转换为音频数据的过程称为合成,而输出合成则称为合成语音。 Text-to-Speech 采用两种类型的输入:原始文本或 SSML 格式的数据(下文详解)。要创建新的音频文件,可调用 API 的 synthesize 端点。

语音合成过程会生成原始音频数据,格式为 base64 编码字符串。您必须先将 base64 编码字符串解码为音频文件,应用才可以播放相应文件。大多数平台和操作系统都具备将 base64 文本解码为可播放媒体文件的工具。

2.3 语音

Text-to-Speech 生成自然人类语音的原始音频数据。也就是说,它生成的音频听上去像人在说话。当您向 Text-to-Speech 发送合成请求时,您必须指定“说出”字词的语音

Text-to-Speech 有多种自定义语音供您选择。语音因语言、性别和口音(适用于某些语言)而异。例如,你可以创建模仿带有英国口音的女性说英语的声音音频,如以上示例 1您也可以将同一文本转换为不同的语音,比方说有澳大利亚口音的男性说英语的声音。

2.4 WaveNet 语音

Text-to-Speech 还同其他传统合成语音一起,提供优质的 WaveNet 生成语音。用户发现 Wavenet 生成语音比其他合成语音更温暖,更像人声。

WaveNet 语音的主要不同之处在于生成语音所用的 WaveNet 模型。WaveNet 模型一直在使用真人发声的原始音频样本进行训练。因此,这些模型生成的合成语音,其音节、音位和字词的重音与音调更像人类。

2.5 其他音频输出设置

除了语音之外,您还可以配置语音合成创建的音频数据输出的其他方面。Text-to-Speech 支持您配置语速、音高、音量和采样率(单位为赫兹)。

2.6 语音合成标记语言 (SSML) 支持

可通过语音合成标记语言 (SSML) 对文本进行标记来增强 Text-to-Speech 生成的合成语音。SSML 可让您在 Text-to-Speech 生成的音频数据中插入暂停、首字母缩写词发音或其他细节。

注意:Text-to-Speech 不支持特定可用语言的部分 SSML 元素。

例如,您可以通过提供具有标记序数词的 SSML 输入的 Text-to-Speech 来确保合成语音正确地读出序数词。

创建服务账号:

为其创建密钥:

添加密钥:

新建 json 类型密钥:

下载该 json 密钥存储到项目路径下:

项目配置该密钥:

为项目启用 API 服务:

3 Voice函数的实现

@app.post("/chat")
def chat(query: str, background_tasks: BackgroundTasks):
    master = Master()
    msg = master.run(query)
    unique_id = str(uuid.uuid4())
    background_tasks.add_task(master.background_voice_synthesis, msg, unique_id)
    return {"msg": msg, "id": unique_id}
def background_voice_synthesis(self, text: str, uid: str):
    # 无返回值,只是触发语音合成
    asyncio.run(self.get_voice(text, uid))
    # text 要转换为语音的文本
    async def get_voice(self, text: str, uid: str):
        print("text2speech", text)
        print("uid", uid)
        print("当前Edge大师应该的语气是:", self.emotion)
        # 默认 grpc 会报 503 错误,必须 rest 请求
        client = texttospeech.TextToSpeechClient(transport="rest")
        input_text = texttospeech.SynthesisInput(text="fsfsdfsd")
        print("input_text=", input_text)
        # Note: the voice can also be specified by name.
        # Names of voices can be retrieved with client.list_voices().
        voice = texttospeech.VoiceSelectionParams(
            language_code="en-US",
            name="en-US-Studio-O",
        )

        audio_config = texttospeech.AudioConfig(
            audio_encoding=texttospeech.AudioEncoding.LINEAR16,
            speaking_rate=1
        )

        response = client.synthesize_speech(
            request={"input": input_text, "voice": voice, "audio_config": audio_config}
        )
        print("response=", response)
        # The response's audio_content is binary.
        with open("output.mp3", "wb") as out:
            out.write(response.audio_content)
            print('Audio content written to file "output.mp3"')

终端输出:

生成文件:

4 语音克隆+TTS增强

4.1 Bark

直达官网,第二代Bark声音克隆 🐶 & 全新中文声音克隆:

4.2 阿里Sambert语音合成

提供SAMBERT+NSFGAN深度神经网络算法与传统领域知识深度结合的文字转语音服务,兼具读音准确,韵律自然,声音还原度高,表现力强的特点。

语音合成API基于达摩院改良的自回归韵律模型,具有推理速度快,合成效果佳的特点。开发者可以通过以下链接,了解如何通过大模型服务平台调用Sambert语音合成API:

Sambert语音合成API基于达摩院改良的自回归韵律模型,支持文本至语音的实时流式合成。可被应用于:

  • 智能设备/机器人播报的语音内容,如智能客服机器人、智能音箱、数字人等。
  • 音视频创作中需要将文字转为语音播报的场景,如小说阅读、新闻播报、影视解说、配音等。
① 将合成音频保存为文件

以下代码展示了将流式返回的二进制音频,保存为本地文件。

import os

from dotenv import load_dotenv

load_dotenv("qwen.env")
import sys
from dashscope.audio.tts import SpeechSynthesizer

result = SpeechSynthesizer.call(model='sambert-zhichu-v1',
                                text='今天天气怎么样',
                                sample_rate=48000)
if result.get_audio_data() is not None:
    with open('output.wav', 'wb') as f:
        f.write(result.get_audio_data())
    print('SUCCESS: get audio data: %dbytes in output.wav' %
          (sys.getsizeof(result.get_audio_data())))
else:
    print('ERROR: response is %s' % (result.get_response()))

② 将合成音频通过设备播放

调用成功后,通过本地设备播放实时返回的音频内容。

运行示例前,需要通过pip安装第三方音频播放套件。

# Installation instructions for pyaudio:
# APPLE Mac OS X
#   brew install portaudio 
#   pip install pyaudio
# Debian/Ubuntu
#   sudo apt-get install python-pyaudio python3-pyaudio
#   or
#   pip install pyaudio
# CentOS
#   sudo yum install -y portaudio portaudio-devel && pip install pyaudio
# Microsoft Windows
#   python -m pip install pyaudio
import dashscope
import sys
import pyaudio
from dashscope.api_entities.dashscope_response import SpeechSynthesisResponse
from dashscope.audio.tts import ResultCallback, SpeechSynthesizer, SpeechSynthesisResult

dashscope.api_key='sk-xxx'

class Callback(ResultCallback):
    _player = None
    _stream = None

    def on_open(self):
        print('Speech synthesizer is opened.')
        self._player = pyaudio.PyAudio()
        self._stream = self._player.open(
            format=pyaudio.paInt16,
            channels=1,
            rate=48000,
            output=True)

    def on_complete(self):
        print('Speech synthesizer is completed.')

    def on_error(self, response: SpeechSynthesisResponse):
        print('Speech synthesizer failed, response is %s' % (str(response)))

    def on_close(self):
        print('Speech synthesizer is closed.')
        self._stream.stop_stream()
        self._stream.close()
        self._player.terminate()

    def on_event(self, result: SpeechSynthesisResult):
        if result.get_audio_frame() is not None:
            print('audio result length:', sys.getsizeof(result.get_audio_frame()))
            self._stream.write(result.get_audio_frame())

        if result.get_timestamp() is not None:
            print('timestamp result:', str(result.get_timestamp()))

callback = Callback()
SpeechSynthesizer.call(model='sambert-zhichu-v1',
                       text='你是睿智的JavaEdge',
                       sample_rate=48000,
                       format='pcm',
                       callback=callback)

执行完后,你就能听到系统语音播放内容了!

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化

  • 活动&券等营销中台建设

  • 交易平台及数据中台等架构和开发设计

  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化

  • LLM应用开发

    目前主攻降低软件复杂性设计、构建高可用系统方向。

参考:

  • 编程严选网

    本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1885452.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

震撼学术界:扩散损失引领图像生成新革命

在人工智能的浪潮中,图像生成技术一直是热门话题。而今,何凯明教授及其团队在这一领域取得了突破性进展,他们提出的扩散损失(Diffusion Loss)技术,为图像生成带来了革命性的速度与效果提升! 传统图像生成的局限 长久以来,图像生成的自回归模型一直依赖于离散值标记…

政务单位网站SSL证书选择策略

在数字化快速发展的今天&#xff0c;政务单位网站作为政府与公众沟通的重要桥梁&#xff0c;其安全性和可信度显得尤为重要。SSL证书作为保障网站安全的重要手段&#xff0c;其选择对于政务单位网站来说至关重要。本文将探讨政务单位网站在选择SSL证书时应该考虑的因素&#xf…

SpringBoot实现图片添加水印(完整)

提示&#xff1a;昨天不是写了一个类似与图片添加水印的版本吗,今天来写一个带数据库&#xff0c;并且可以完整访问的版本 文章目录 目录 文章目录 引入库 配置文件 数据库配置 字段配置 索引配置 数据库表语句 启动文件 前端代码 整体代码目录 配置类AppConfig Contro…

行业分析---造车新势力之极氪汽车

1 前言 在之前的博客中&#xff0c;笔者撰写了多篇行业类分析的文章&#xff08;科技新能源&#xff09;&#xff1a; 《行业分析---我眼中的Apple Inc.》 《行业分析---马斯克的Tesla》 《行业分析---造车新势力之蔚来汽车》 《行业分析---造车新势力之小鹏汽车》 《行业分析-…

LangChain入门学习笔记(七)—— 使用检索提高生成内容质量

大模型训练使用的数据是开放的、广泛的&#xff0c;因此它显得更加的通用。然而在有些应用场景下&#xff0c;用户需要使用自己的数据使得大模型生成的内容更加贴切&#xff0c;也有时候用户的数据是敏感的&#xff0c;无法提供出来给大模型进行通用性的训练。RAG技术就是一种解…

mysql mgr集群断电重启

一、前言 mysql mgr集群所有节点都断电重启时&#xff0c;就会面临一个问题&#xff0c;应该怎么重新构建mgr集群 二、操作 查询所有节点的master状态 show master status; 查看同步状态&#xff0c;可以通过uuid知道是通过哪个节点进行同步的数据 查看所有节点的uuid&#x…

【CT】LeetCode手撕—82. 删除排序链表中的重复元素 II

题目 原题连接&#xff1a;82. 删除排序链表中的重复元素 II 1- 思路 模式识别1&#xff1a;已排序链表 ——> 判重逻辑 &#xff0c;涉及到 while 2- 实现 ⭐82. 删除排序链表中的重复元素 II——题解思路 class Solution {public ListNode deleteDuplicates(ListNode h…

2019:Cornfields

网址如下&#xff1a; OpenJudge - 2019:Cornfields 唉&#xff0c;最近沉迷法环&#xff0c;都没怎么学习了 话说这题的名字让我想起了《星际穿越》了&#xff08;玉米地呀玉米地&#xff09; 这是翻译过后的版本&#xff0c;题目要求我们帮助FJ找到放置玉米地的最佳位置&am…

深入STM32的ADC世界:从理论到实践,打造精准数据采集系统

摘要: 在嵌入式系统中&#xff0c;模拟信号的采集与处理至关重要。本文将深入浅出地介绍STM32的ADC模块&#xff0c;结合实际项目&#xff0c;详细阐述ADC的工作原理、配置方法以及数据处理技巧&#xff0c;并辅以Mermaid图表和代码示例&#xff0c;助你轻松掌握ADC应用开发。 …

回流焊常见缺陷

不润湿(Nonwetting)/润湿不良(Poor Wetting) 通常润湿不良是指焊点焊锡合金没有很好的铺展开来,从而无法得到良好的焊点并直接影响到焊点的可靠性。 产生原因: 1. 焊盘或引脚表面的镀层被氧化,氧化层的存在阻挡了焊锡与镀层之间的接触; 2. 镀层厚度不够或是加工不良,很…

arm-linux-gnueabihf-gcc:Command not found 解决办法

问题描述 使用虚拟机交叉编译程序&#xff0c;当使用了sudo去编译, 出现arm-linux-gnueabihf-gcc&#xff1a;Command not found的问题。明明已经安装并配置好环境了&#xff0c;发现还是提示找不到编译器。 原因分析&#xff1a; 特意去查了一下sudo方法&#xff0c;我们在sud…

chunk-vendors.js 优化

问题背景 在 App.vue 加入 web-vitals 性能监控指标并打印 import {onLCP, onINP, onCLS, onTTFB} from web-vitals/attribution;// Measure and log LCP as soon as its available. onLCP(console.log); onINP(console.log); onCLS(console.log); onTTFB(console.log);网页的…

linux开发常用工具和命令

文章目录 服务器文件挂载服务器终端挂载vscode编辑服务器代码linux开发常用命令dulnllobjdump 服务器文件挂载 在本地操作服务器文件。 在文件夹右侧‘其他位置‘’—>‘链接到服务器s’ sftp://usernameip/目录&#xff0c;回车后输入密码即可在左侧看到映射的服务器文件夹…

网络基础-RIP协议

RIP&#xff08;Routing Information Protocol&#xff09;是一个基于距离矢量的动态路由协议&#xff0c;常用于小型到中型网络。RIP是较早的路由协议之一&#xff0c;具有简单易用的特点。以下是关于RIP协议的详细介绍&#xff1a; RIP的主要特点 ①使用跳数&#xff08;ho…

自己分析的逆向案例八——中国新烟商盟登录密码加密

网址&#xff1a;会员登录 - 新商盟 登陆界面分析&#xff0c;找到登录接口&#xff0c;跟栈分析。 没有异步&#xff0c;也没有webpack,很简单的跟栈 打上断点&#xff0c;逐步网上找&#xff0c;找到$ajax老朋友 上面就有对密码加密的部分&#xff0c;是一个RSA加密。 b 被…

认识100种电路之耦合电路

在电子电路的世界中&#xff0c;耦合电路宛如一座精巧的桥梁&#xff0c;连接着各个功能模块&#xff0c;发挥着至关重要的作用。 【为什么电路需要耦合】 在复杂的电子系统中&#xff0c;不同的电路模块往往需要协同工作&#xff0c;以实现特定的功能。然而&#xff0c;这些模…

C++ STL unique_ptr智能指针源码剖析

由于上一篇博客将shared_ptr,weak_ptr,enable_shared_form_this的源码实现整理了一遍,想着cpp智能指针还差个unique_ptr故写下此篇博客,以供学习 源码剖析 一,模板参数 首先,我们先看unique_ptr的模板参数,第一个参数_TP自是不用说表示对象类型,第二个模板参数定义了unique_p…

新书速览|Adobe Firefly:萤火虫:AI绘画快速创意设计

《Adobe Firefly&#xff1a;萤火虫&#xff1a;AI绘画快速创意设计》 本书内容 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;浪潮的席卷已经变成不可阻挡的趋势&#xff0c;伴随着这种变化&#xff0c;在图形设计、图像制作、绘画领域也相应发生了…

程序员鱼皮的写简历指南(保姆级)1、基本写法

大家好&#xff0c;我是程序员鱼皮。做知识分享这些年来&#xff0c;我看过太多简历、也帮忙修改过很多的简历&#xff0c;发现很多同学是完全不会写简历的、会犯很多常见的问题&#xff0c;不能把自己的优势充分展示出来&#xff0c;导致错失了很多面试机会&#xff0c;实在是…

一篇搞懂!LinuxCentos中部署KVM虚拟化平台(文字+图片)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f468;‍&#x1f4bb;Linux高级管理专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月28日15点11分 &#x1f004;️文章质量&#xff1a;94分 目录 ————前言———— KVM的优点 KVM…