前提
- Amazon Connectのコンタクトフローより音声データストリーミングを有効化し、Kinesis Video Streamsへデータストリーミングを行います。
- リアルタイムで音声データを送信する必要があり、通話が始まるとECSを起動して、リアルタイムで音声データの加工・送信を行います。
- 通話中は無限ループ内でリアルタイムで取得するストリーミングデータをGetMedia APIより取得し、データ加工を行い外部APIへデータ送信を行います。
- 通話終了後にEventBridgeを使用して通話終了トリガー用のLambdaを起動し、終話フラグをオンにすることでデータ送信処理を終了させています。
はじめに行っていたデータ取得方法
GetMedia APIよりデータ取得を行い、transformToByteArray
を使用して変換を行いデータ送信を行おうとしていました。
while(!isEndCalling ){ //終話フラグ
const getMediaForFragmentListResponse = await kvsMediaClient.getMedia(getMediaCommand);
const payload = getMediaForFragmentListResponse.Payload;
const binary = await payload.transformToByteArray();
// ~~ データ送信 ~~
}
awaitを使って非同期関数を呼び出す場合、JavaScriptの実行はそのプロミスが解決されるまで待機します。
transformToByteArray
がストリーミングデータを扱う場合、データストリームの終わり(EOF)が明確でないため、プロミスはデータストリームが終了するまで(つまり、通話が終了するまで)解決されません。
つまり、GetMedia APIで取得したストリーミングデータの終端をtransformToByteArray
が検知できないため、通話が終了するまで解決されません。
解決方法
GetMediaForFragmentListを使用する
GetMediaではなくGetMediaForFragmentListを使用することで解決できます。
GetMediaForFragmentListは開始時刻と終了時刻を指定してデータ取得を行うAPIです。
つまり,データストリームの終わりが明確となるため、上記問題を解決することができます。
while(!isEndCalling ) { //終話フラグ
const getMediaForFragmentListResponse = await kvArchivedMediaClient.getMediaForFragmentList(getMediaForFragmentListCommand);
const payload = getMediaForFragmentListResponse.Payload;
const binary = await payload.transformToByteArray();
// ~~ データ送信 ~~
}
実装上の注意点
1. 適切な時間範囲の設定
GetMediaForFragmentListを使用する際は、適切な時間範囲を設定する必要があります。
適切な時間範囲の設定をしないと、必要なデータが取得できていなかったり、逆に不必要なデータを取得してしまう可能性があります。
2. データの連続性の確保
連続したデータストリームを処理する場合、各呼び出しの時間範囲が重複しないよう注意する必要があります。
1.で記載した適切な時間範囲の設定を行うことで、データの連続性を確保することができます。
3. listFragmentsで取得されるフラグメントは順不同
listFragmentsで取得されるフラグメントは順不同となっているため、フラグメントタイムスタンプでソートしないとバラバラになってしまうことがあります。
参考
まとめ
Amazon Connectのリアルタイムのストリーミングデータ処理において、GetMedia APIを使用した方法では、データストリームの終端検知が困難でした。この問題を解決するために、GetMediaForFragmentList APIの使用しました。
開始時刻と終了時刻を指定してデータ取得が可能であり、データストリームの終わりが明確になり、処理の完了を適切に処理することができますが、適切な時間範囲の設定とデータの連続性を確保する必要があります。