非同期音声通知
notify メッセージを使うと、デバイスがアイドル状態のときに、クラウドが一方向の音声通知を再生できます。対話用の音声チャネルは開かず、マイクのアップリンクも有効にしません。対話を始めるには、これまでどおりユーザーが明示的にウェイクする操作が必要です。
メッセージ形式
クラウドは、デバイスが現在使っているプロトコルの制御接続を通じて、次の JSON を送ります。MQTT デバイスの場合は、既存の MQTT 制御トピックです。
{
"type": "notify",
"audio_url": "https://cdn.example.com/audio/task-complete.ogg",
"subtitles": [
{
"start_ms": 0,
"text": "Your task is complete."
},
{
"start_ms": 1800,
"text": "The result has been saved."
}
]
}audio_url は必須です。http:// と https:// のどちらの URL も受け付けます。HTTP はローカルネットワークでの開発に便利で、本番環境では URL の生成時に HTTPS を強制できます。
subtitles は省略可能です。各項目には、メディアの開始時刻(ミリ秒)と表示するテキストが入ります。デバイスは項目を start_ms で並べ替え、再生位置が新しい字幕の項目を越えたときだけ表示を更新します。
このメッセージには、確認応答、通知 ID、状態、種別、有効期限のフィールドはありません。配信はベストエフォートで、オンラインのデバイスにのみ適用されます。
音声レスポンス
audio_url は、モノラル・単一ストリームの Ogg Opus ファイルを含む 2xx の成功レスポンスを返す必要があります。Content-Length を持つレスポンスも、チャンク転送エンコーディングのレスポンスも使えます。デバイスはリダイレクトに従いません。
ファイルは少しずつ読み込まれます。デバイスはレスポンス全体の長さに応じてメモリを確保せず、再生前にファイル全体をダウンロードすることもありません。通知のストリーミングでは、既存の容量制限付き HTTP レスポンスキュー、2 KB の Ogg 論理パケットバッファ、共有の 20 パケットの Opus デコードキュー、既存の 2 フレーム分の PCM 再生キューを使います。デコードキューは、ファームウェアの通常のパケット長 60 ms で 1.2 秒分に相当します。これらのバッファが TCP のバックプレッシャーを働かせるので、PSRAM のないデバイスでもこの機能を使えます。
独立した LiteAudioEngine の WakeNet を使うデバイスでは、通知の再生中は WakeNet のリソースを解放し、デバイスが Idle に戻るときに再作成します。AFE を使うデバイスは、これまでのローカルウェイクの動作を維持します。
Opus のパケット長は、MQTT メッセージで指定するのではなく、Opus の TOC バイトから読み取ります。ファームウェアのデコーダーが対応する、5 ms から 120 ms までの整数ミリ秒のパケット長を受け付けます。現在の実装は、ステレオのストリーム、検出された Ogg または Opus の構造エラー、不完全なストリーム、サイズ超過の論理パケット、2.5 ms のパケットを拒否します。
デバイスの動作
デバイスは Idle 状態のときだけ notify を受け付けます。受け付けると、次の動作を行います。
- 内部の
Notifying状態に入り、ボードをパフォーマンスモードに切り替えます。 - 通常の音声処理とマイクのアップリンクを無効にします。
- 以前の再生内容を消去し、内蔵のポップアップ音をキューに入れます。
- バックグラウンドタスクで HTTP GET を 1 回開始します。
- Ogg パケットを少しずつ分離し、既存の Opus デコードキューに直接送ります。
- Opus パケットが音声出力タスクに到達したメディア位置に合わせて、字幕を表示します。
- HTTP ストリームが正常に終了し、キューにあった音声がすべて再生されてから、
Idleに戻ります。
ポップアップ音は HTTP タスクの開始前にキューに入れられるので、リモートの音声がそれより先に再生されることはありません。HTTP 接続の確立は、ポップアップ音の実際の再生と重なって進みます。
リモート音声の再生が始まったあと、HTTP ストリームが終わる前にすべての再生キューが空になった場合、デバイスは Notification playback underrun #<count> at <position> ms とログに出力します。ポップアップ音からストリームへの切り替えと、通常の再生終了は、アンダーランとして扱いません。
デバイスは UDP 音声チャネルを開かず、start-listening を送らず、自動で Listening にも入りません。AFE を使うデバイスは、再生中もローカルのウェイクワード検出を続けることがあります。再生エコーキャンセルのないデバイスは、既存の発話中ウェイクの動作を維持し、ハードウェアのウェイク操作でも通知をキャンセルできます。
ウェイク操作を行うと、HTTP のプロデューサーをキャンセルし、キューにある通知音声を消去し、通常のウェイクの流れに進みます。ネットワークの切断、HTTP エラー、不正な音声でも再生はキャンセルされ、デバイスは Idle に戻ります。デバイスがビジー状態のときに届いた 2 件目の通知は無視されます。
xz-mqtt による転送
xz-mqtt は、既存の Redis RPC メソッドでこのメッセージを転送します。
{
"method": "forward",
"clientId": "device-client-id",
"params": {
"type": "notify",
"audio_url": "https://cdn.example.com/audio/task-complete.ogg",
"subtitles": [
{
"start_ms": 0,
"text": "Your task is complete."
}
]
}
}RPC の結果には、MQTT の送信処理が返した真偽値が入ります。
{
"success": true
}この結果は、xz-mqtt が現在オンラインのデバイスの接続にパブリッシュメッセージを書き込んだことを意味します。受信や再生の確認ではありません。xz-mqtt は、UDP セッションの作成、チャットブリッジの起動、Ogg ファイルのプロキシ、オフラインのデバイス向けの通知の保持を行いません。