利用TTS,讓你的AI Agent發(fā)聲!
1 語音邏輯設(shè)計
一個AI Agent應(yīng)用的語音邏輯設(shè)計流程圖。
1.1 基本流程
- 用戶 -> Agent -> 文本回答
最基礎(chǔ)的交互模式。用戶輸入被傳遞給Agent,Agent生成文本回答。
1.2 添加語音功能
- 用戶 -> Agent -> 文本回答
|
v
TTS服務(wù) -> MSTTS -> 語音回答
基本流程基礎(chǔ)上,增加文本轉(zhuǎn)語音(TTS)服務(wù)。Agent生成的文本回答被發(fā)送到TTS服務(wù),然后通過MSTTS(Microsoft Text-to-Speech)轉(zhuǎn)換為語音回答。
1.3 完整流程
- 用戶 -> Agent -> 文本回答
|
v (異步)
TTS服務(wù) -> MSTTS -> 語音回答
文本回答和語音回答是并行處理的。Agent生成文本回答后,同時開始TTS轉(zhuǎn)換過程,這個過程被標(biāo)記為"異步"。
1.4 設(shè)計思路
- 模塊化:將文本處理和語音轉(zhuǎn)換分離,便于獨(dú)立開發(fā)和維護(hù)。
- 異步處理:文本回答可以立即呈現(xiàn),而語音轉(zhuǎn)換在后臺進(jìn)行,提高響應(yīng)速度。
- 靈活性:可以根據(jù)需求選擇只使用文本回答或同時使用語音回答。
- 技術(shù)整合:利用MSTTS等成熟技術(shù),提高語音質(zhì)量。
這種設(shè)計允許AI Agent應(yīng)用在保持高效文本交互的同時,提供更豐富的語音交互體驗(yàn)。
2 TTS能力介紹
以 Google Cloud Text-To-Speech 服務(wù)為例說明。
開發(fā)人員可用 Text-to-Speech 創(chuàng)建可播放音頻格式的自然發(fā)音的合成人類語音??捎糜?Text-to-Speech 創(chuàng)建的音頻數(shù)據(jù)文件來豐富應(yīng)用功能或者擴(kuò)大視頻或錄音等媒體。
Text-to-Speech 會將文本或語音合成標(biāo)記語言 (SSML) 輸入轉(zhuǎn)換為音頻數(shù)據(jù),例如 MP3 或 LINEAR16(WAV 文件中使用的編碼)。
2.1 基本示例
Text-to-Speech 適用于向用戶播放人類語音音頻的任何應(yīng)用。您可以使用它將任意字符串、字詞和句子轉(zhuǎn)換為表述相同內(nèi)容的人的語音。
設(shè)想您有一個語音輔助應(yīng)用,可以通過可播放音頻文件,向您的用戶提供自然語言反饋。您的應(yīng)用可能會執(zhí)行某個操作,然后向用戶提供人類語音作為反饋。
例如,您的應(yīng)用可能想要報告它已成功將某項(xiàng)活動添加到用戶的日歷中。您的應(yīng)用會構(gòu)建一個響應(yīng)字符串向用戶報告操作已成功,例如“我已將活動添加到您的日歷中”。
使用 Text-to-Speech,您可以將該響應(yīng)字符串轉(zhuǎn)換為實(shí)際的人類語音以播放給用戶,類似于下面提供的示例。
示例 1:Text-to-Speech 生成的音頻文件
要創(chuàng)建音頻文件,請向 Text-to-Speech 發(fā)送請求,如:
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 語音合成
將文本輸入轉(zhuǎn)換為音頻數(shù)據(jù)的過程稱為合成,而輸出合成則稱為合成語音。Text-to-Speech 采用兩種類型的輸入:原始文本或 SSML 格式的數(shù)據(jù)(下文詳解)。要創(chuàng)建新的音頻文件,可調(diào)用 API 的 synthesize
端點(diǎn)。
語音合成過程會生成原始音頻數(shù)據(jù),格式為 base64 編碼字符串。您必須先將 base64 編碼字符串解碼為音頻文件,應(yīng)用才可以播放相應(yīng)文件。大多數(shù)平臺和操作系統(tǒng)都具備將 base64 文本解碼為可播放媒體文件的工具。
2.3 語音
Text-to-Speech 生成自然人類語音的原始音頻數(shù)據(jù)。也就是說,它生成的音頻聽上去像人在說話。當(dāng)您向 Text-to-Speech 發(fā)送合成請求時,您必須指定“說出”字詞的語音。
Text-to-Speech 有多種自定義語音供您選擇。語音因語言、性別和口音(適用于某些語言)而異。例如,你可以創(chuàng)建模仿帶有英國口音的女性說英語的聲音音頻,如以上示例 1您也可以將同一文本轉(zhuǎn)換為不同的語音,比方說有澳大利亞口音的男性說英語的聲音。
2.4 WaveNet 語音
Text-to-Speech 還同其他傳統(tǒng)合成語音一起,提供優(yōu)質(zhì)的 WaveNet 生成語音。用戶發(fā)現(xiàn) Wavenet 生成語音比其他合成語音更溫暖,更像人聲。
WaveNet 語音的主要不同之處在于生成語音所用的 WaveNet 模型。WaveNet 模型一直在使用真人發(fā)聲的原始音頻樣本進(jìn)行訓(xùn)練。因此,這些模型生成的合成語音,其音節(jié)、音位和字詞的重音與音調(diào)更像人類。
2.5 其他音頻輸出設(shè)置
除了語音之外,您還可以配置語音合成創(chuàng)建的音頻數(shù)據(jù)輸出的其他方面。Text-to-Speech 支持您配置語速、音高、音量和采樣率(單位為赫茲)。
2.6 語音合成標(biāo)記語言 (SSML) 支持
可通過語音合成標(biāo)記語言 (SSML) 對文本進(jìn)行標(biāo)記來增強(qiáng) Text-to-Speech 生成的合成語音。SSML 可讓您在 Text-to-Speech 生成的音頻數(shù)據(jù)中插入暫停、首字母縮寫詞發(fā)音或其他細(xì)節(jié)。
注意:Text-to-Speech 不支持特定可用語言的部分 SSML 元素。
例如,您可以通過提供具有標(biāo)記序數(shù)詞的 SSML 輸入的 Text-to-Speech 來確保合成語音正確地讀出序數(shù)詞。
創(chuàng)建服務(wù)賬號:
圖片
為其創(chuàng)建密鑰:
圖片
添加密鑰:
圖片
新建 json 類型密鑰:
圖片
下載該 json 密鑰存儲到項(xiàng)目路徑下:
圖片
項(xiàng)目配置該密鑰:
圖片
為項(xiàng)目啟用 API 服務(wù):
圖片
3 Voice函數(shù)的實(shí)現(xiàn)
@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):
# 無返回值,只是觸發(fā)語音合成
asyncio.run(self.get_voice(text, uid))
# text 要轉(zhuǎn)換為語音的文本
async def get_voice(self, text: str, uid: str):
print("text2speech", text)
print("uid", uid)
print("當(dāng)前Edge大師應(yīng)該的語氣是:", self.emotion)
# 默認(rèn) 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("respnotallow=", 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增強(qiáng)
4.1 Bark
直達(dá)官網(wǎng),第二代Bark聲音克隆 ?? & 全新中文聲音克隆:
圖片
4.2 阿里Sambert語音合成
提供SAMBERT+NSFGAN深度神經(jīng)網(wǎng)絡(luò)算法與傳統(tǒng)領(lǐng)域知識深度結(jié)合的文字轉(zhuǎn)語音服務(wù),兼具讀音準(zhǔn)確,韻律自然,聲音還原度高,表現(xiàn)力強(qiáng)的特點(diǎn)。
語音合成API基于達(dá)摩院改良的自回歸韻律模型,具有推理速度快,合成效果佳的特點(diǎn)。開發(fā)者可以通過以下鏈接,了解如何通過大模型服務(wù)平臺調(diào)用Sambert語音合成API:
Sambert語音合成API基于達(dá)摩院改良的自回歸韻律模型,支持文本至語音的實(shí)時流式合成??杀粦?yīng)用于:
- 智能設(shè)備/機(jī)器人播報的語音內(nèi)容,如智能客服機(jī)器人、智能音箱、數(shù)字人等。
- 音視頻創(chuàng)作中需要將文字轉(zhuǎn)為語音播報的場景,如小說閱讀、新聞播報、影視解說、配音等。
① 將合成音頻保存為文件
以下代碼展示了將流式返回的二進(jìn)制音頻,保存為本地文件。
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()))
圖片
② 將合成音頻通過設(shè)備播放
調(diào)用成功后,通過本地設(shè)備播放實(shí)時返回的音頻內(nèi)容。
運(yùn)行示例前,需要通過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)
執(zhí)行完后,你就能聽到系統(tǒng)語音播放內(nèi)容了!