Genesys AudioHookは8 kHzのµ-law——そして立つ場所はどこにもない
Genesys CloudのAudioHookプロトコルは、サンプルレートを型システムに固定しています。MediaRateはリテラルの8000であり、仕様のどこにも16000という文字列は現れません。AudioHook Monitorは一方向のタップで、サーバーの出力は明示的に破棄されます。Audio Connectorは音声を再生できますが、それはIVR内のボットフォークであり、フローを一時停止し、エージェントには決して届きません。そのメディア経路で第三者に何ができて何ができないかを仕様ごとに読み解き、確認できなかった4つの事項は未確認として名指しします。
以下の仕様に関する主張はすべて、Genesys自身が公開しているドキュメントから引用し、リンクしています。確認できなかったものは、埋めて済ませるのではなく未確認として挙げています——そのためのセクションが末尾近くにあります。これらのいずれかが誤っている、あるいは変わった場合には、教えてください。日付を付して訂正します。
コンタクトセンターは音声AIが実際の売上と出会う場所であり、Genesys Cloudはその中でも最大級のひとつです。したがって、音声処理を売るすべての者にとって重要な問いは、狭く、答えられるものです。メディア経路はどのような姿をしていて、その中に第三者が立てる場所はあるのか?
Genesysの答えは異例なほど読み取りやすいものです。彼らはプロトコルを説明するのではなく、公開しているからです。サンプルレートの問題の全体は、彼らの型定義に現れるとおり、これだけです。
type MediaFormat = 'PCMU';
type MediaRate = 8000;
デフォルトではありません。推奨でもありません。リテラル型です。プロトコルリファレンスは散文でこれを繰り返し——「メディアフォーマットのサンプルレート(ヘルツ単位)。Genesys Cloudクライアントは現在8000Hzのみをサポートする」——そして16000という文字列はAudioHook仕様のどこにも現れません。
これこそ、このサイト全体が主題にしているくさびが、プラットフォーム自身の言葉で述べられたものです。文書化されたプロトコルを通じてGenesys Cloudに音声を統合するすべての第三者は、狭帯域のG.711 µ-lawを受け取ります。そして市場にある音声強調モデルは本質的にすべて広帯域で訓練されています。
トランスポート、手短に
AudioHookは、予想されるであろう役割を逆転させます。GenesysがWebSocketのクライアントで、あなたのサービスがサーバーです。
「AudioHookプロトコルはトランスポートとしてTLS上のWebSocketを使用し、それを受け入れるサーバーを実装しやすいように設計されている。」——イントロダクション
具体的には、セキュリティページとセッションウォークスルーから:
| プロパティ | 値 |
|---|---|
| ポート | 443、そして443のみ |
| TLS | 1.2と1.3。証明書はパブリックCAの署名が必須(自己署名は不可) |
| フレーミング | テキストフレームにJSON、バイナリフレームに生音声 |
| 最大メッセージサイズ | テキストもバイナリも同じく64,000バイト |
| オープン/ping/クローズのタイムアウト | 5,000 ms / 5,000 ms / 10,000 ms |
| アプリケーションpingの間隔 | 接続ごとに5秒おき |
| 認証 | X-API-KEYヘッダー、加えて任意のHMAC-SHA256リクエスト署名(ノンス必須) |
| リトライ | 最大5回、指数バックオフ |
実装者を噛むので、取り出しておく価値のあるディテールが2つあります。
このpingはWebSocketのpingではありません。 これらはアプリケーションレベルのping/pong JSONメッセージであり——「WebSocketのping/pongメッセージ(これらは使用されない)とは別個のプロトコル機能」——要求されていないpongはプロトコルエラーです。5秒ごとに、5秒以内に答えなければ、Genesysは接続を失われたものとして扱い、再確立するかもしれません。
WebSocketサブプロトコルは存在しません。 私たちはこれを特に探しました。文書化されたハンドシェイクはAudiohook-Organization-Id、Audiohook-Correlation-Id、Audiohook-Session-Id、X-API-KEYのヘッダーを運び、Sec-WebSocket-Protocolは一切ありません。この文字列はAudioHook仕様のどのページにも現れません。サブプロトコルでルーティングするつもりだったなら、代わりにパスでルーティングしてください。
メディアネゴシエーション、そして2つのチャネルの正体
openメッセージはオファーを運び、あなたのopened応答がそこから選びます。SDP方式です。ルールは厳格です。
「サーバーはオファーされたエントリのうち正確にひとつを選択しなければならず、オファーされたメディアフォーマット(チャネルとその順序を含む)を変更してはならない。これはSIP/SDPメディアネゴシエーションのオファー・アンサー交換に似ているが、より単純である。」——セッションウォークスルー
典型的なオファーは3エントリで、すべて8000 HzのPCMU、チャネルだけが異なります:["external", "internal"]、["external"]、["internal"]。
このチャネル名こそ人々が間違える部分であり、「caller」と「agent」ではありません。AudioHookが追うのはレッグではなく参加者です。
「現在、2つの値がサポートされている。
externalは、その参加者が表す当事者が話す内容を表し、internalは、その当事者が聞く内容を表す。」——プロトコルリファレンス
つまりinternalはその参加者が聞くすべてです——IVRプロンプトかもしれず、ACDの保留音楽かもしれず、カンファレンスではミックスであり得ます。Genesysは明示的にそう述べています。「私たちのAudioHookにおける「internal」チャネルの音声は、両方のエージェントの音声のミックスを表す」。1チャネルに1つの声を仮定するものを作っているなら、その仮定はウォームトランスファーで崩れます。ステレオの応答では、左がインデックス0、右がインデックス1です。
フレームサイズ:そんなものは存在しない
これは最初の実装でバグが生まれる可能性が最も高い箇所であり、仕様はそれについて率直です。
「フレームあたりのサンプル数は可変であり、クライアントに委ねられている……サーバーは音声フレームのサイズについて一切の仮定を置いてはならず、サンプルを数えることで音声ストリームのタイムラインを維持すること。」——セッションウォークスルー
与えられている唯一の具体的な数字は例示です。8000 Hzの2チャネルPCMUの100 msフレームは1600バイトで、ヘッダーなし、インターリーブ。あなたのフレーミング予算は、64,000バイトのメッセージ上限とレート制限——バイナリメッセージは平均で毎秒10、バーストで25まで、テキストも同じ——です。
そしてこのストリームは、電話のようにはペーシングされません。Genesysはバッファします。
「クライアントは少なくとも20秒の音声の履歴バッファを維持する……バッファされた音声を実時間より速くサーバーへ送り、その後、実時間のストリームを続ける。クライアントが『追いつく』レートは未定義である。」
つまりセッションは、不特定のレートでの履歴のバーストで開き、その後実時間に落ち着きます。固定ブロックサイズで作られたあらゆるもの——ストリーミングの音声強調(speech enhancement)モデルはすべてそうで、私たちのものも含みます——は、その手前に独自の再フレーミングバッファを必要とし、実時間係数を壁時計の到着時刻から測るものは、最初の数秒間ナンセンスな値を示します。
クライアントは追いつけなくなると、startとdiscardedの継続時間と不変条件position = start + discardedを運ぶdiscardedメッセージで、あなたにそれを告げます。これはギャップの告知であって、制御コマンドではありません。「音声の予期しない喪失により音声ストリームに不連続が生じたときはいつでも」。明示的なポーズと再開はこれを生みません。タイムラインを維持するためにサンプルを数えているなら——仕様はそうせよと言っています——discardedは、タイムラインがいま動いたことをあなたが知る方法です。
すべてを決める問い:音声を送り返せるか
それは、4つのAudioHook機能のどれを実装しているかに完全に依存し、その答えは互いに似ていません。
| 機能 | あなたのサーバーへの音声 | 通話への音声の返送 | 返せるもの |
|---|---|---|---|
| AudioHook Monitor | あり。externalとinternalの片方または両方 | なし | 帯域内では何も返せない |
| Audio Connector | あり。externalのみ | あり——通話者に再生される | 音声(ボットのプロンプトとして) |
| Transcription Connector | あり | なし | transcriptイベント |
| Bot Transcription Connector | あり(PCMUまたはL16) | なし | transcriptと発話イベント |
AudioHook Monitorはタップであり、自らそう言っています。 機能ページは解釈の余地を残しません。
「ここではクライアントが会話音声をサーバーへストリームするが、帯域内データをクライアントへ送り返すことはできない。サーバーから返されたデータは黙って無視され、破棄される。」
黙って、に注意してください。エラーでも警告でもなく——あなたの処理済み音声は消え、セッションは健全に見えます。イントロダクションはプロトコル全体を同じ枠で捉えています。「これは、参加者の当事者との間の音声ストリームに対する「タップ」だと考えてほしい」。
Audio Connectorは正真正銘、双方向です。そしてこれこそ、最初は突破口に見えるものです。
「この機能は双方向の音声ストリーミングをサポートする……クライアントに送られた音声データはすべて通話者に再生される。 クライアントからサーバーへ送られるのは
external音声チャネルのみである。」——機能
それにふさわしい機構も備えています。playback-startedとplayback-completedのクライアントメッセージ、barge_inサーバーイベント、dtmfメッセージです。サーバーからクライアントへの音声は「1メッセージあたり64,000バイト以下」に制限され、ペーシングされます——「サーバーは200msより頻繁に音声を送るべきではない」。
1日を費やす前に知っておく価値のある、文書化された矛盾がひとつあります。同じプロトコルリファレンスのエラー表は、いまだに逆のことを言っています。
「
415Unsupported Media Type——サーバーがクライアントへバイナリメッセージを送った……サーバーからクライアントへの音声送信はサポートされていない。」
私たちの読みはこうです。415はAudio Connector以前のもので、MonitorとTranscription Connectorのセッション——そこではサーバーからのバイナリは確かに不正です——に適用されます。変更履歴は、双方向音声、DTMF、再生、バージイン(barge-in)が後の更新で到着したことを示しています。しかし仕様は今日、両方の記述を含んでおり、これに向けて構築するなら、自分のセッションタイプにどちらが適用されるかは経験的に発見することになると見込んでおくべきです。
それでもAudio Connectorが挿入点ではない理由
ここからは、プロトコルではなくアーキテクチャが扉を閉める場所です。Audio Connectorはインラインのフィルタではなくボットのターンであり、その3つの性質は、他人のボットの前で音声をクリーンにしようとする者にとって、それぞれ単独で失格要因です。
「ArchitectのCall Audio Connectorアクションは音声ストリームをフォークし、設定されたURLへ送り、その時点で、双方向ストリームが終わるまでフロー実行を一時停止する……双方向ストリーミングセッションがアクティブなのはIVRチャネル内のみである。エージェントへは引き継がれない。」——Audio Connector概要
- あなたが送る音声は、ボットではなく通話者へ行きます。 あなたは電話の向こう側の声になることを求められているのです。「クリーンにした通話者音声を返し、プラットフォーム自身の音声認識器にそちらを聞かせる」という向きは存在しません。存在する向きは人間を指しています。
- これはフローをブロックするフォークです。 実行はアクションで停止し、あなたのセッションが終わると再開します。それはダイアログのターンであって、パイプラインの段ではありません。
- エージェントには決して届きません。 IVR限定です。
加えて、同じページに文書化された小さめの制約もあります。双方向ストリームは1本、チャネルはexternalのみ、Audio Connectorの同時通話は300、通話あたりの上限は900秒、そしてBYOC Premisesではサポートなし。
したがって、面をひとつずつ確かめた上での正直な結論はこうです。Genesys Cloudが文書化しているのは、音声の持ち出し、IVRレッグでの音声ダイアログ、そしてメタデータの返送です。第三者が音声を受け取り、処理し、その処理済み音声を、プラットフォーム自身の下流の消費者が聞くものにする方法は、どこにも文書化されていません。 私たちはMonitor、Audio Connector、Transcription Connector、Bot Transcription Connector、Genesys Agent Assist(音声経路を一切持たないナレッジ提示機能)、Genesys Bot Connector(テキストとインテント、メッセージフローのみ)、そしてBring Your Own Interactions(事後の取り込みであってライブメディアではない)を確認しました。
立てる場所はあり、それは正確にひとつ
現実の挿入点はひとつ存在し、それは人々が探す場所ではありません。
あなた自身が音声認識器であるなら、自分自身の認識器の前で音声をクリーンにできます。 Bot Transcription Connectorは、第三者がSTTエンジンになることをまさに可能にするために存在し——「STTエンジンとして機能するAudioHookベースのサーバーへ音声をストリームすることを可能にする」——Genesys自身のヘルプセンターはこれを「Genesys AudioHookプロトコルを使ってサードパーティのASRエンジンを統合する」方法として説明しています。この経路はPCMUを受け取り、この経路だけはL16も提供し、音声ではなくtranscriptと発話開始イベントを返します。
これは問いに答えるのではなく、問いを移転させます。その境界の内側では、チェーン全体があなたのものです。8 kHzのµ-lawが入り、あなたの処理、あなたの認識器、トランスクリプトが出る。そこにフィルタを置くことを、プラットフォームの何も妨げません。妨げているのは、私たち自身の測定の上では、そこに置ける物のほとんどが現時点では悪い選択だということです。私たちの7つのテレフォニー条件で、テストしたどのエンジンも未処理音声に対する意味のある改善を生まず、いくつかは単語誤り率(WER)を5〜10ポイント劣化させました。立てる場所は存在します。欠けていたのは、そこに携えて立つ価値のある何かであり、それこそがこの会社が存在する理由のすべてです。
二次的な帰結は、プラットフォーム選定をしている人のために明言しておく価値があります。AudioHookでは、あなたの最大ボリュームのチャネルについての音質の決定は、あなたの上流で下され、あなたには変えられません。 あなたが得るのは8 kHzのµ-lawと、キャリアレッグがそれに施した何かであり、あなたが持つ唯一のレバーは、届いた後に何をするかです。
確認できなかったこと
明示的に名指しします。隙間を黙って埋める開発者向けの記事には、何の価値もないからです。
- Genesys自身の文字起こしのサンプルレート。 彼ら自身のSTTがどのレートで動くかについてのGenesysの言明はひとつも見つけられず、8 kHz対16 kHzの比較もどこにもありませんでした。彼らのエンジンはベンダー製(Google、Microsoft Azure、AWS Transcribe、Genesysネイティブエンジン、Deepgram)で、どれについてもレートは公表されていません。トランクコーデックはG.722とOpusを含み得るので、キャリアレッグは必ずしも狭帯域ではありません——しかし文字起こし器に届くものは文書化されていません。本記事の8000 Hzという数字は、AudioHookの第三者経路のみのものです。 私たちの言葉を根拠に、これをGenesys自身のパイプラインへ拡張しないでください。
- BYOCのSIP経路にSBCやメディアサーバーを挿入して音声を加工する、サポートされた方法。 BYOC CloudではサードパーティキャリアへのSIPトランクを定義でき、トランクコーデックは設定可能です。その経路に処理要素を置くことを支持する、説明する、あるいは禁止するGenesysの文書は見つかりませんでした。文書の不在は許可ではなく、禁止でもありません。
- AudioHook Monitorの同時接続数の最大値。 公表されているのはインテグレーションとモニターの数だけです——AudioHook Monitorインテグレーションは5、インテグレーションのインストールは最大20、設定済みモニターは最大500、Transcription Connectorインテグレーションは10。私たちが見つけた唯一の同時実行の数字は、Audio Connectorの同時通話300です。
- Audio Connectorにおける、サーバーからクライアントへの音声のワイヤフォーマット。 仕様はケイデンス(200 msより頻繁にしない)とサイズ上限(64,000バイト)を与えますが、フォーマットを改めて述べることはありません。おそらくネゴシエートされたものでしょう。しかし、そうだとは書かれていません。
- 「AudioHook Media Service」はGenesysの製品名ではないようです。開発者センターのサイトマップとヘルプセンターの記事索引の全体を検索し、何も見つかりませんでした。この用語を見かけたことがあるなら、それはGenesysのドキュメントから来たものではありません。
また、GenesysがTypeScriptによるリファレンスサーバー実装をクライアントツールとテストスイートつきで公開していること、そして別にAudio Connectorリファレンスサーバーがあり、そのソースがMediaFormatを'PCMU' | 'L16'に、MediaRateを8000に、最大バイナリメッセージを64000にピン留めしていることも記しておきます——上の数字の、散文ではなくコードによる、2つ目の独立した確認です。
これを実装するなら
- フレームではなく、サンプルを数えること。 仕様はそれを要求しており、キャッチアップのバーストは、そうしないあらゆるものを罰します。
- 自分のモデルのブロックサイズへバッファすること。 そして最初の20秒間は、到着タイミングを音声タイミングの代理として決して使わないこと。
discardedはタイムラインのイベントとして処理すること。 ログに書いて通り過ぎるエラーとしてではなく、です。そうしなければ、その後のあなたのサンプルカウンタは間違っています。pingには常に5秒以内に答えること。 それも、推論にブロックされ得ない経路から。モデルとコントロールプレーンがイベントループを共有していれば、一度の遅いブロックが接続を食います。- 何かを設計する前に、自分がどの機能なのかを決めること。 MonitorとAudio Connectorは同じプロトコルに見えて正反対のアーキテクチャであり、エラー表は、間違ったほうを作ることを止めてくれません。
- PCI境界に注意すること。 AudioHookはセキュアフロー中にセキュアポーズが実行されることでPCI DSSコンプライアンスに適合しており、セキュアフロー中の音声ストリーミングには使えません。あなたが作るものには設計上の穴があり、その穴は意図されたものです。
Amazon Connect、Twilio、NICE CXone、Avayaを扱う姉妹記事は、同じ問いを残りの4プラットフォームに対して読み解きます——そして、そのうちのひとつは、Genesysが文書化していないものを文書化していることが分かります。