Pipecatの独自TTSサービス:音声ボットに好きな声を
Pipecatは、音声ボットやマルチモーダルボットのためのオープンソースのPythonフレームワークです。フレームプロセッサーのパイプラインが、相手の音声を音声認識、言語モデル、音声合成に通して返します。多くの音声プロバイダー向けのサービスがあり、新しいものも小さなクラスを1つ書くだけで追加できます。
このガイドでは、そのクラスをSuperClonicaの音声合成API向けに書きます。ボットはキャラクター、ナレーター、アナウンサーを含むカタログの190の声や、自分の録音から学習させた声で話せるようになります。
PipecatのTTSサービスのしくみ
TTSサービスはTTSServiceを継承し、run_tts(テキストの断片を受け取り、16ビットPCMの音声フレームを返す非同期ジェネレーター)を実装します。Pipecat 1.14で確認したところ、既定ではモデルのテキストを文ごとにまとめるので、run_ttsは1文に1回呼ばれ、モデルが書いている間に最初の文が再生されます。基底クラスには、WAVヘッダーを取り除いてパイプラインのサンプルレートにリサンプリングするヘルパーもあります。
pip install pipecat-ai aiohttp
サービス
これをsuperclonica_pipecat.pyとしてボットの隣に保存します:
import os
import aiohttp
from pipecat.frames.frames import ErrorFrame
from pipecat.services.settings import TTSSettings
from pipecat.services.tts_service import TTSService
URL = "https://superclonica.com/api/v1/speech"
class SuperClonicaTTSService(TTSService):
def __init__(self, *, session: aiohttp.ClientSession, voice: str, language: str = "en", **kwargs):
super().__init__(
push_start_frame=True,
push_stop_frames=True,
settings=TTSSettings(model=None, voice=voice, language=language),
**kwargs,
)
self._session = session
self._voice, self._language = voice, language
def can_generate_metrics(self):
return True
async def run_tts(self, text: str, context_id: str):
headers = {"Authorization": "Bearer " + os.environ["SUPERCLONICA_KEY"]}
body = {"text": text, "voice": self._voice, "language": self._language, "format": "wav"}
async with self._session.post(URL, json=body, headers=headers) as answer:
if answer.status != 200:
yield ErrorFrame(error=f"SuperClonica: {answer.status} {await answer.text()}")
return
await self.start_tts_usage_metrics(text)
async for frame in self._stream_audio_frames_from_iterator(
answer.content.iter_chunked(self.chunk_size), strip_wav_header=True, context_id=context_id
):
await self.stop_ttfb_metrics()
yield frameサービスはAPIにWAV(標準の44バイトのヘッダーの後に44.1 kHzの16ビットモノラルPCM)を要求し、そのバイト列をヘルパーに渡します。ヘルパーはヘッダーを取り除き、16 kHzや24 kHzなどパイプラインの出力レートにリサンプリングしてフレームを返します。プランの枠を使い切ったときの429など、APIがエラーを返した場合は、ステータスとメッセージ付きのErrorFrameを返します。
ボットで使う
aiohttpのセッションと選んだ声のページに表示されるIDでサービスをつくり、Pipelineの今のTTSサービスの位置に置きます:
import os
import aiohttp
from superclonica_pipecat import SuperClonicaTTSService
session = aiohttp.ClientSession()
tts = SuperClonicaTTSService(session=session, voice=os.environ["VOICE_ID"], language="en")
# put tts in your Pipeline where your current TTS service isSUPERCLONICA_KEYに音声合成APIのページで作ったキーを設定します。ボットのトランスポート、音声認識、言語モデルはそのままです。
遅延とプラン
短い文ではWAVは合成が終わるとまとめて届き、約30秒を超える長さのテキストはAPIがストリーミングします。私たちの計測では、約300 msとネットワークの時間で話し始めます。プランは10分ごとの枠で、すべての通話を合わせた音声の秒数を決めます。無料キーは開発用に1日1分、月5ドルのスタートは枠ごとに最大3分、Proは20分です。Supertonic 3は31言語を話しますが中国語にはまだ対応しておらず、APIは単語ごとのタイムスタンプを返しません。