HTTP2 接続の維持
概要
Alexa Voice Service(AVS)ではHTTP/2エンドポイントを提供し、タイマーやアラーム、メディア操作の制御、音声制御による音量調整、Amazon Alexaアプリ統合といったAlexa標準機能へのアクセスを可能にする、クラウドで開始するディレクティブをサポートします。このページでは、AVSとのHTTP/2接続を作成し、維持する方法について説明します。
重要な用語と概念
- フレーム: HTTP/2での基本的なプロトコル構成単位です。フレームごとに異なる目的を持ちます。たとえば、HEADERSフレームとDATAフレームが、HTTPのリクエストと応答の基盤となります。
- ストリーム: 独立した、双方向の連続したフレームです。HTTP/2接続においては、このストリームがクライアント/サーバー間でやり取りされます。詳細については、RFC 7540におけるストリームとマルチプレクシングを参照してください。
- インターフェース: AVSでは、製品がAlexaの標準スキルにアクセスするためのインターフェース(SpeechRecognizer、AudioPlayer、SynchronizeStateなど)を公開しています。
- ダウンチャネル: HTTP/2接続で作成したストリームのうち、クラウドからクライアントにディレクティブを配信するために使用するもの。ダウンチャネルは、接続のライフタイムの間、端末側からはクローズ、AVS側からはオープンの半閉鎖状態でオープンのままになります。ダウンチャネルは、主にクラウドで開始されたディレクティブをクライアントに送信するために使われます。
注: クライアントが作成できるダウンチャネルストリームは、接続ごとに1つのみです。
- クラウドで開始されるディレクティブ: クラウドからクライアントに送信されるディレクティブ。たとえば、ユーザーがAmazon Alexaアプリから端末の音量を調整するとき、対応する音声リクエストなしで製品にディレクティブが送信されます。
前提条件
AVSとのHTTP/2接続を作成する前に、以下の条件を満たす必要があります。
-
アクセストークンを取得する
製品からAVSにアクセスするには、ユーザーに代わって製品からAPIにアクセスできるようにするLogin with Amazon(LWA)アクセストークンを取得する必要があります。AVSで使用するためのアクセストークンの取得方法には、2つの方法があります。
リモート認可は、コンパニオンウェブサイトまたはモバイルアプリを使用して端末を認可する場合に使用されます。
ローカル認可は、AVS対応製品から直接Alexaを認可する場合に使用します。
取得するLWAアクセストークンは、各イベントのヘッダーにあるAVSに送信される必要があります。何らかの理由で認可が失敗した場合は、AVSとの接続が切断されます。
以下は、ヘッダーのサンプルです。AVSに送信される各イベントのヘッダーには、アクセストークンに加えて、バウンダリ文字列も指定する必要があります。
:method = POST :scheme = https :path = /{{API version}}/events authorization = Bearer {{YOUR_ACCESS_TOKEN}} content-type = multipart/form-data; boundary={{BOUNDARY_TERM_HERE}}
注: 各製品インスタンスは、認可中にスコープデータで渡される一意のdeviceSerialNumber
を持つ必要があります。 -
HTTP/2クライアントライブラリを選択する
AVSでの使用に推奨されるHTTP/2クライアントライブラリは以下のとおりです。
言語 ライブラリ C / C++ nghttp2 C / C++ curlおよびlibcurl Java OkHttp Java Netty Java Jetty 実装の全リストについては、GitHubを参照してください。
注意: libcurlを使用している場合、クライアントは接続を維持するため、5分おきに、/ping
に対してGET
リクエストを実行する必要があります。詳細については、下のPingとタイムアウトを参照してください。
ベースURL
リージョン | 対応している国 | URL |
---|---|---|
North America | 米国 | https://avs-alexa-na.amazon.com |
Europe | 英国、ドイツ | https://avs-alexa-eu.amazon.com |
HTTP/2接続の作成
製品の電源を入れたら、AVSとの間にシングルHTTP2接続を作成する必要があります。この接続は、ダウンチャネルストリーム上でクライアントに送信されるものを含め、すべてのディレクティブとイベントを処理するために使用されます。接続の管理に関するその他の詳細については、下のサーバー側からの接続解除を参照してください。
AVSとの接続を維持するには、以下の2点が必要となります。
- ダウンチャネルストリームの確立
- 製品のコンポーネントの状態とAVS(SpeechRecognizer、AudioPlayer、Alerts、Speaker、SpeechSynthesizer)との同期
RecognizerState
は、クライアントでクラウドベースのウェイクワード検証を使用する場合にのみ必要です。-
ダウンチャネルストリームを確立するには、AVSとの接続をオープンしてから10秒以内に、
//directives
に対してGET
リクエストを実行する必要があります。リクエストは、以下のようになります。:method = GET :scheme = https :path = /{{API version}}/directives authorization = Bearer {{YOUR_ACCESS_TOKEN}}
リクエストが成功した後、ダウンチャネルは、接続のライフタイムの間、クライアント側からはクローズ、AVS側からはオープンの半閉鎖状態でオープンのままになります。クラウドで開始されたディレクティブ間に長い一時停止時間があることは、珍しいことではありません。
-
ダウンチャネルストリームを確立した後、クライアントはコンポーネントの状態をAVSと同期する必要があります。これには、existing connection上の新規のイベントストリームで、
//events
へのPOST
リクエストを行う必要があります(注: 新しい接続をオープンしないでください)。このイベントストリームは、クライアントが応答(ディレクティブ)を受信したときにクローズされる必要があります。以下は、SynchronizeState
イベントの例です。:method = POST :scheme = https :path = /{{API version}}/events authorization = Bearer {{YOUR_ACCESS_TOKEN}} content-type = multipart/form-data; boundary={{BOUNDARY_TERM_HERE}} --{{BOUNDARY_TERM_HERE}} Content-Disposition: form-data; name="metadata" Content-Type: application/json; charset=UTF-8 { "context": [ {{Alerts.AlertsState}}, {{AudioPlayer.PlaybackState}}, {{Speaker.VolumeState}}, {{SpeechSynthesizer.SpeechState}} {{SpeechRecognizer.RecognizerState}} ], "event": { "header": { "namespace": "System", "name": "SynchronizeState", "messageId": "{{STRING}}" }, "payload": { } } } --{{BOUNDARY_TERM_HERE}}--
状態の同期後、クライアントはこの接続を以下の目的で使用できます。
- AVSにイベントを送信し、AVSからディレクティブを受信する
注: 各イベントと関連する応答は、1つのイベントストリーム上で送信されます。応答を受信すると、ストリームはクローズされます。
- ダウンチャネルストリーム上で、クラウドで開始されたディレクティブを受信する
HTTP/2接続の維持
接続を確立したら、イベントストリーム、ダウンチャネルストリーム、ping、タイムアウト、およびサーバーで開始された接続解除を管理する方法を理解することが重要です。
考慮すべき点
-
キャプチャしたオーディオは、10ミリ秒で320バイトのチャンクごとに、ストリーミングでAVSに送信することを推奨します(320バイトのデータフレームを1つの単位として送信)。チャンクサイズを大きくすると不要なバッファリングが発生し、AVSがオーディオを処理する能力に悪影響を及ぼし、レイテンシーが高くなる可能性があります。
AVSに送信されるすべてのキャプチャされたオーディオは、以下のようにエンコードされる必要があります。
- 16bit Linear PCM (LPCM16)
- 16kHz sample rate
- Single channel
- Little endian byte order
完全な仕様については、SpeechRecognizerインターフェースを参照してください。
-
AVSとのHTTP/2接続が同時にサポートするストリームの数は、10までです。これには、イベントストリーム、ダウンチャネル、pingも含まれます。応答を受信するときにはイベントストリームがクローズされていることを確認してください。
-
ライブラリの多くでは、クライアントがデータを受信することなく読み取りを試行する時間の長さとして、読み取りタイムアウトを設定できます。AVSでは、接続のライフタイムの間、AVSとクライアント間のダウンストリームをオープンのままにしておく必要があり、同じストリームがクライアントにデータを送信することなく延長期間に入る可能性があることから、読み取りタイムアウトを少なくとも60分に設定しておくことが重要です。
-
HTTP/2クライアントに接続プーリングがあり、接続がアイドル状態にある場合、タイムアウトを調整して接続が中断されないようにすることが重要です(また、接続作成のフローを完了するために中断された場合(ダウンチャネルストリームの再確立とAVSとの状態の同期を含む)も同様です)。接続が途中でクローズされることがないよう、タイムアウトは少なくとも60分に設定することを推奨します。
イベントストリームのライフサイクル
新しいイベントは、それぞれ独自のストリーム上で送信されます。通常、これらのストリームは、Alexa Voice Serviceがディレクティブと対応するオーディオ添付ファイルをクライアントに返した後でクローズされます。
リクエストは、順に処理されます。そのため、新しいリクエストはAlexaが前のリクエストへの応答を開始した後(前のリクエストがヘッダーを返したら)で送信する必要があります。
- 製品はストリームをオープンし、JSON形式のイベント1つと、0または1つのバイナリオーディオ添付ファイルで構成されるマルチパートメッセージを送信します。詳細については、HTTP/2リクエストの構成を参照してください。
- AVSは、もう1つのJSON形式のディレクティブと対応するオーディオ添付ファイルで構成されるマルチパートメッセージを同じストリーム上で返します(ストリーミングが完了する前の可能性があります)。
Play
またはSpeak
ディレクティブ内でcid:
の後に指定されるurl属性も、関連するオーディオ添付ファイルのヘッダーに存在します。 - AVSからの応答の後、イベントストリームをクローズする必要があります。
ダウンチャネルのライフサイクル
並行して、ディレクティブがダウンチャネル上でクライアントに送信される場合があります。ダウンチャネルは、主にクラウドで開始されたディレクティブに使用されます。
GET
リクエストは、AVSとの接続の作成から10秒以内にディレクティブのパスに対して行われます。- このストリームは、クライアントに、タイマー、アラーム、Amazon Alexaアプリから出した指示など、クラウドで開始されたディレクティブを送信するために使用されます。イベントストリームと異なり、ダウンチャネルはすぐにはクローズされず、延長期間の間、クライアント側からはクローズ、AVS側からはオープンの半閉鎖状態でオープンのままになるよう設計されています。
- ダウンチャネルストリームがクローズされると、クライアントはすぐに新しいダウンチャネルを確立し、クラウドで開始されるディレクティブを確実に受信できるようにする必要があります。
Pingとタイムアウト
クライアントは以下のアクションのいずれかを実行する必要があり、失敗した場合は接続がクローズされます。
- 接続がアイドル状態のとき、AVSに対して5分ごとに
PING
フレームを送信する。 - 接続がアイドル状態のとき、
/ping
に対して5分ごとにGET
リクエストを行う。
リクエストのサンプル
:method = GET :scheme = https :path = /ping authorization = Bearer {{YOUR_ACCESS_TOKEN}}
PINGに失敗したら、接続はクローズされ、すぐに新しい接続が作成される必要があります。
/ping
に対してGET
リクエストを実行する必要があります。サーバーで開始された接続解除
サーバーで接続解除を開始すると、クライアントは以下のアクションを実行する必要があります。
- 新しい接続をオープンし、新しいリクエストはすべてこの接続にルーティングする。
- すべての未完了のリクエストが処理され、対応するストリームが正常にクローズされたら、古い接続をクローズする。
- 接続解除が開始される前に確立したすべてのストリームURLへの接続を維持させます(Amazon Music、Audibleなど)。サーバーで接続解除が開始される前に再生していたストリームは、処理するバイトがある間は再生を続ける必要があります。
新しい接続を作成しようとして失敗したら、クライアントはexpotential back-offを利用して再送をする必要があります。 *ezpotential back-offとは失敗回数に応じて再送信する待ち時間を指数関数的に増やす仕組みです。
次のステップ
リクエストを構成する方法の詳細については、以下を参照してください。