LiveKit Agentsのワーカーにスピーカーアイソレーションを追加するには?
ワーカーのstt_node内で、受信音声にAnecho SDKを16 kHz・240サンプルのホップで適用します。LiveKit用のプラグインパッケージはないため、この記事では自分で書くコードを、リサンプリングの注意点と数値とともに示します。
LiveKit Agentsのワーカーにスピーカーアイソレーションを追加するには、受信音声フレームを音声認識の段階に届く前にAnecho SDKへ通します。16 kHz、240サンプルのホップです。 livekit-plugins-anecho というパッケージは存在せず、当社は公開していません。以下はSDKの契約をLiveKitのフレーム型に適用した、あなたが所有するコードです。
契約
SDKには3つのオブジェクトがあります。Model(ダッシュボードの .anecho ファイル)、Processor(float32を入力し、同じ数のサンプルを15 ms遅れで出力)、UsageReporter(ライセンスのハートビート。送るのは時間だけで、音声は送りません)。モデルは16 kHz、240サンプルのホップで動作します。ストリームの最初の240サンプルは無音で返り、これがアルゴリズム遅延です。
フレームループ
Agentsでは stt_node が rtc.AudioFrame の非同期イテレータを受け取ります。これをラップし、ホップに再分割し、プロセッサを通して同じ形のフレームを返します。
import os
import numpy as np
from scipy.signal import resample_poly
from livekit import rtc
from livekit.agents import Agent
from anecho import Model, Processor, UsageReporter
RATE, HOP = 16_000, 240 # model rate; 240 samples = 15 ms
reporter = UsageReporter(os.environ["ANECHO_API_KEY"])
model = Model.from_file("anecho.ai_focus_model_16khz_v8_2.anecho") # from your dashboard
class IsolatedAgent(Agent):
async def stt_node(self, audio, model_settings):
async def isolated():
proc = Processor(model, reporter.ensure_license()) # one per call
reporter.attach(proc)
reporter.start()
pending = np.zeros(0, dtype=np.float32)
async for frame in audio: # rtc.AudioFrame, int16
x = np.frombuffer(frame.data, dtype=np.int16).astype(np.float32) / 32768.0
if frame.num_channels > 1: # mix down to mono
x = x.reshape(-1, frame.num_channels).mean(axis=1)
if frame.sample_rate != RATE: # e.g. 48000 -> 16000
x = resample_poly(x, RATE, frame.sample_rate).astype(np.float32)
pending = np.concatenate([pending, x])
while len(pending) >= HOP:
block, pending = pending[:HOP], pending[HOP:]
y = proc.process(block) # same length out, 15 ms behind
pcm = (np.clip(y, -1.0, 1.0) * 32767).astype(np.int16)
yield rtc.AudioFrame(
data=pcm.tobytes(), sample_rate=RATE,
num_channels=1, samples_per_channel=HOP,
)
return Agent.default.stt_node(self, isolated(), model_settings)
これはAgents 1.xの Agent.stt_node フックに対するスケッチです。稼働中のLiveKitワーカーでのベンチマークはしていないため、お使いのAgentsバージョンでフックのシグネチャを確認し、自社のトラフィックで試してください。
リサンプリングの注意点
- LiveKitのフレームはint16で、48 kHzや24 kHzが一般的です。モデルは16 kHzのfloat32を要求するので、サンプルを間引くのではなく、適切なポリフェーズフィルタ(上の
resample_poly)でプロセッサの前にリサンプリングしてください。 - リサンプリングは1回だけにします。STT側でもリサンプリングする場合、アイソレーション後の16 kHz音声が多くの認識器の望む形式です。
- 電話レッグは8 kHzで届きます。16 kHzにアップサンプリングしても帯域は戻りません。8 kHzは音声AIが壊れる場所を参照してください。
- 録音や第二の消費者がある場合は生の分岐を残してください。分割パイプラインを参照してください。
コストとプラットフォームの選択肢
| 項目 | 値 | 出典と日付 |
|---|---|---|
| アルゴリズム遅延 | 15 ms | Null Test、2026-08-14 |
| 実時間係数、CPU 1スレッド | 0.067 | Null Test、2026-08-14(Apple M1 Max) |
| 最悪ブロック時間、p99 | 3.96 ms | Null Test、2026-08-14 |
| 月10,000無料分のあとの当社エントリー料金 | 1分あたり$0.0010 | anecho.ai/pricing |
| LiveKit Cloudのボイスアイソレーション、プラン枠超過分 | 1分あたり$0.0012 | livekit.com/pricing、2026-10-15取得 |
LiveKit Cloudはボイスアイソレーションを従量課金の項目として販売しており、Krispとai-cousticsのモデルが割り当てられています(livekit.com/pricing と docs.livekit.io、2026-10-15取得)。ワーカーをLiveKit Cloudで動かし、そのどちらかが合うなら、妥当な選択です。SDKを自分で動かせば音声はプロセス内に留まり、ワーカーがどこで動いても使えます。2つの価格は同じ条件ではありません。当社は公開の段階制での処理分あたり、LiveKitはプランごとです。アイソレーションが自社のトラフィックに効くかは既定値ではなく計測で決まります:話者分離の評価方法。
FAQ
LiveKit Agents向けのAnechoプラグインはありますか?
いいえ。公開されたプラグインパッケージはありません。SDKはPythonとNodeのライブラリで、この記事が統合コードを示します。
LiveKitのパイプラインのどこにプロセッサを置きますか?
受信音声に対し、音声認識の前、stt_node フック内です。
どれくらいの遅延が加わりますか?
15 msのアルゴリズム遅延で、2026-08-14のNull Testにて、CPU 1スレッドで実時間係数0.067と計測しています。