音声入力を使用した本番環境対応のライブ音声文字変換の実装(チュートリアル)

このチュートリアルでは、音声入力Google Kubernetes Engine(GKE)Memorystore を使用して、オーディオ ストリームのリアルタイムの音声文字変換を実行するアプリを作成します。このアプリは高可用性と復元力を備えるよう設計されており、本番環境用の音声文字変換アプリのベースラインを提供します。このチュートリアルで作成するアプリのコードは、GitHub リポジトリにあります。

このチュートリアルは、音声入力を使用した本番環境対応のライブ音声文字変換のアーキテクチャガイドに対応しています。ユースケースと設計上の決定について詳しくは、このドキュメントをご覧ください。

目標

  • GKE クラスタと Memorystore インスタンスを作成します。
  • アプリのマイクロサービスをビルドして GKE クラスタにデプロイします。
  • 音声ファイルをストリーミングして、アプリの動作を検証します。
  • エラーを発生させてアプリの復元力をテストします。

費用

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Cloud Console のプロジェクト セレクタページで、Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud Build API and the Speech-to-Text, GKE, and Memorystore API を有効にします。

    API を有効にする

アーキテクチャ

次の図は、このチュートリアルでデプロイするアーキテクチャを表したものです。

本番環境に対応した音声文字変換アプリの Google Cloud 上におけるインフラストラクチャのアーキテクチャ

このアーキテクチャには、次の機能が含まれています。

  • 3 つのアプリのマイクロサービス:
    • Ingestor: このサービスはソース音声ストリームを取り込みます。
    • Transcriber: このサービスでは音声入力を呼び出し、音声文字変換結果を出力します。
    • Reviewer: このサービスは、審査のために音声文字変換結果をウェブアプリに表示します。
  • GKE。複数のゾーンにまたがるリージョン GKE クラスタでアプリのマイクロサービスをホストします。アプリのマイクロサービスはゾーンをまたいでデプロイされます。
  • Memorystore for Redis。高速な中間ストレージとして使用されます。これは高可用性構成でデプロイされます。
  • ロードバランサ。以下のことを行うためにアプリ機能をインターネットに公開します。
    • ソース音声ストリームの転送先 IP アドレスを指定します。
    • 審査担当者のウェブアプリを提供します。

このチュートリアルでは、次のクライアントでアプリ機能をテストします。

  • 音声ファイルを Ingestor サービスにストリーミングする音声クライアント スクリプト。
  • Reviewer サービスからの音声文字変換テキストを表示するデモ用ウェブ クライアント。

Google Cloud インフラストラクチャの作成

  1. Cloud Shell で、Cloud プロジェクト ID の変数を作成します。

    export PROJECT_ID=project-id
    

    project-id を、このチュートリアル用に作成したか選択した Cloud プロジェクトの ID に置き換えます。

  2. アクティブな Cloud Shell セッションのプロジェクトを設定します。

    gcloud config set project $PROJECT_ID
    
  3. GKE のリージョン クラスタを作成して起動します。

    gcloud container clusters create transcription-cluster \
        --cluster-version=1.14 \
        --region=us-central1 \
        --node-locations=us-central1-a,us-central1-b \
        --num-nodes=1 \
        --machine-type=n1-highcpu-2 \
        --scopes=cloud-platform \
        --enable-ip-alias \
        --metadata disable-legacy-endpoints=true
    

    このチュートリアルでは、us-central1 リージョンにリソースを作成します。チュートリアル内のタスクでは、リージョン内の 2 つのゾーンでの 1 つのノードで十分です。

    このタスクが完了するまで数分かかることがあります。

  4. GKE クラスタと同じリージョンにスタンダード ティアの Memorystore インスタンスを作成します。

    gcloud redis instances create redis-captions \
        --tier=standard \
        --region=us-central1 \
        --zone=us-central1-a
    

    スタンダード ティアのインスタンスは、レプリケーションと自動フェイルオーバーを使用した高可用性を提供します。インスタンスは、指定されたゾーン内のプライマリ ノードと、リージョン内の別のゾーンのレプリカで構成されます。このタスクが完了するまで数分かかることがあります。

  5. 次のようにして、Memorystore インスタンスの IP アドレスを格納する環境変数を作成します。

    export REDIS_HOST=`gcloud redis instances describe redis-captions \
        --region=us-central1 --format='value(host)'`
    

マイクロサービスのデプロイ

  1. Cloud Shell で、デプロイするアプリのコードを含む GitHub リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/solutions-speech-productionized-transcription
    
    
  2. リポジトリ ディレクトリに移動します。

    cd solutions-speech-reliable-transcription
    
  3. Cloud Build パイプラインを起動して、アプリのマイクロサービスの Docker コンテナをビルドします。

    gcloud builds submit --config cloudbuild.yaml
    

    ビルドされたコンテナは、プロジェクトの Container Registry に保存されます。

  4. Cloud プロジェクト ID を使用するように Kubernetes YAML 構成ファイルを変更します。

    sed -i "s/myproject/$PROJECT_ID/" k8s/*.yaml
    
  5. Kubernetes YAML 構成ファイルを変更して、Memorystore インスタンスの IP アドレスを設定します。

    sed -i "s/redisHost=.*/redisHost=$REDIS_HOST/" k8s/*.yaml
    
  6. IngestorTranscriberReviewer のマイクロサービスを GKE クラスタにデプロイします。

    kubectl apply -f \
        k8s/ingestor.yaml,k8s/transcriber.yaml,k8s/reviewer.yaml
    
  7. GKE クラスタに 3 つの Kubernetes Deployment がすべて作成されていることを確認します。

    kubectl get deployments
    

    出力は次のようになります。各 Deployment には 2 つの Pod があるので注意してください。

    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    ingestor-deployment     2/2     2            2           13s
    reviewer-deployment     2/2     2            2           12s
    transcriber-deployment  2/2     2            2           12s
    
  8. GKE クラスタに IngestorReviewer の Kubernetes Service が作成されていることを確認します。

    kubectl get services
    

    出力は次のようになります。

    NAME               TYPE           CLUSTER-IP   EXTERNAL-IP
    ingestor-service   LoadBalancer   10.0.9.193   35.224.219.112
    kubernetes         ClusterIP      10.0.0.1     <none>
    reviewer-service   LoadBalancer   10.0.9.203   35.223.138.37
    
  9. 環境変数を Ingestor サービスの外部 IP アドレスに設定します。

    export INGEST_IP=`kubectl get services ingestor-service \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}'`
    
  10. Ingestor ページのコンテンツを取得して、ページが使用可能であることを確認します。

    curl $INGEST_IP; echo
    

    ページが機能している場合は、Hello メッセージが表示されます。

  11. Reviewer サービスの外部 IP アドレスで環境変数を設定し、変数の値をコンソールに表示します。

    export REVIEWER_IP=`kubectl get services reviewer-service \
        -o jsonpath='{.status.loadBalancer.ingress[0].ip}'`; \
        echo $REVIEWER_IP
    
  12. 前述のコマンドで表示された REVIEWER_IP アドレスをコピーします。

  13. ローカルマシンで、今コピーした IP アドレスにブラウザタブでアクセスします。

    Live Transcription demo というテキストを表示する審査担当者のウェブページが表示されます。音声文変換テキストは後でこのウェブページに書き込まれるので、ページを開いたままにしておいてください。

音声ストリームの音声文字変換の確認

このセクションでは、デプロイしたばかりのアプリに音声ファイルをストリーミングし、生成された音声文字変換テキストを調べます。音声は、ルイス・キャロル著の『鏡の国のアリス』の「ハンプティ・ダンプティ」の章の最初の数行を読み上げたものです。音声入力で音声がどの程度音声文字変換されるかを比較するには、Guutberg.org サイト上のこの章のテキストをご覧ください。

音声クライアントは、リアルタイムで、信頼性の高い、双方向通信を提供するオープンソース パッケージである SocketIO ライブラリを使用して、音声を Ingestor サービスにストリーミングします。同様に、Reviewer サービスは、SocketIO を使用してデモ用のウェブ クライアントに音声文字変換を提供します。

Transcriber サービスには、サンプル音声ファイルの特性と一致する音声入力の構成が含まれています。具体的には、オーディオのサンプルレート(44,100 kHz)、オーディオ チャンネルの数(単一チャンネル、モノラル)、入力言語(英語)が定義されます。別の音声ファイルをストリーミングする場合は、入力オーディオに合わせて構成を更新する必要があります。

  1. Cloud Shell で、クライアント ディレクトリに移動します。

    cd client
    
  2. 新しい Python 3 仮想環境を作成して有効にします。virtualenv ユーティリティは、すでに Cloud Shell にインストールされています。

    virtualenv -p python3 venv
    source venv/bin/activate
    
  3. デモ用ウェブ クライアントに必要な Python パッケージをインストールします。

    pip install -r requirements.txt
    
  4. 音声クライアント スクリプトを実行して、音声ファイルを Ingestor サービスにストリーミングします。

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    
  5. ローカルマシンで、審査担当者のウェブページに戻ります。

    ページにストリーミングされた音声文字変換テキストが表示されます。

  6. 音声入力の音声文字変換テキストをその章のテキストと比較して、音声文字変換の精度を判断します。

    次のスクリーンショットは、テキストと音声文字変換テキストの例を示しています。

    元のテキストが上部に、音声文字変換テキストが下部に表示されます。

  7. Cloud Shell で Ctrl+C キーを押して音声ストリーミングを停止します。

音声文字変換のフェイルオーバーのテスト

コンパニオン ガイドで説明されているように、Transcriber サービスはリーダー選出パターンを使用して、単一の Transcriber Pod のみが音声入力に接続し、残りの Pod は効率的なフェイルオーバーのためにホット スタンバイとして動作します。このセクションでは、リーダー Pod が削除されたときに音声文字変換の出力をモニタリングしてフェイルオーバーの動作を確認します。

復元プロセスの一環として新しい Transcriber Pod がリーダーとして選出されると、新しいリーダーは最後に受信した音声の最後の数秒間を再生します。これにより、以前のリーダーがオフラインになったときにオーディオ損失を最小限に抑えることができます。このアプローチでは、前の音声が再生されるため、音声文字変換の単語が重複することがあります。本番環境アプリでは、音声文字変換を使用するプロセスで重複を調整する必要があります。

  1. ローカルマシンで、ブラウザタブを更新して審査担当者のウェブページから存在する音声文字変換テキストを消去します。

  2. Cloud Shell で、音声クライアントを再起動します。

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    

    審査担当者のウェブページに音声文字変換テキストが表示されます。

  3. 別の Cloud Shell タブを開き、2 つの Cloud Shell タブが開くようにします。

  4. 新しい Cloud Shell タブで、環境変数をプロジェクト ID に設定します。

    export PROJECT_ID=project-id
    

    project-id を、このチュートリアル用に作成したか選択した Cloud プロジェクトの ID に置き換えます。

  5. リポジトリ ディレクトリに移動します。

    cd solutions-speech-reliable-transcription
    
  6. リーダー音声文字変換 Pod を削除します。

    python3 deleter.py --leader --iterations 3 --delay 15
    

    スクリプトは Kubernetes コントロール プレーンにクエリを実行して、現在のリーダー Pod の ID を取得してから、Pod を削除します。コマンドはリーダーを 3 回削除し、イテレーションごとに 15 秒待機します。

  7. 審査担当者のウェブページをモニタリングします。

    音声文字変換ストリームに [REPLAY] 通知が表示されます。これは、新しい Transcriber Pod がリーダーに選出され、音声データの最後の数秒間が再生されていることを示します。音声文字変換で単語が重複して表示される場合があります。フェイルオーバーが非常に高速であること、音声文字変換の出力の中断が最小限であることを確認します。

  8. Transcriber Deployment にまだ 2 つの Pod があることを確認します。

    kubectl get pods -l=app=transcriber
    

    出力は次のようになります。

    NAME                                      READY   STATUS
    transcriber-deployment-7f57746c7c-rjwm5   2/2     Running
    transcriber-deployment-7f57746c7c-t7srr   2/2     Running
    

    Transcriber は Kubernetes Deployment であるため、指定された数の Pod のレプリカが作成されるように、Kubernetes は自動的に新しい Pod を作成します。

  9. 1 つ目の Cloud Shell タブに戻り、Ctrl+C キーを押して音声クライアントを停止します。

他のマイクロサービスの Pod の削除

前のセクションでは、Transcriber Pod が削除されても音声文字変換テキストの配信が中断されないことを確認しました。このセクションでは、他のマイクロサービスの Pod が削除されたときのアプリの動作をテストします。

Ingestor Pod と Reviewer Pod は、LoadBalancer 型の Kubernetes Service によってインターネットに公開されます。クライアントは固定 IP アドレスを使用して各 Kubernetes Service に接続し、Kubernetes は使用可能な Pod にトラフィックをルーティングします。Ingestor Pod または Reviewer Pod が削除されると、Kubernetes は対応する Service を更新して、トラフィックが存在しない Pod に転送されないようにします。同様に、その後、Pod レプリカの構成された数に合わせて新しい Pod が作成されると、トラフィックが新しい Pod に送信されるように Service が更新されます。

このアプリでは、この動作によってトラフィックがアプリを通過するようにします。Ingestor Service と Reviewer Service の両方にはそれぞれ Pod が 2 つあるため、片方の Pod が削除されると Kubernetes は準備ができていてトラフィックの処理を開始できるもう片方の Pod にトラフィックを迅速にリダイレクトできます。

音声クライアントとデモ用ウェブ クライアントは両方とも SocketIO を使用して Ingestor Service と Reviewer Service に接続します。SocketIO の接続が切れると、自動的に再接続を試みます。こうして、現在の Pod が削除されると、クライアントは同じ Service IP アドレスを使用して新しい Pod に再接続します。

Ingestor Pod を削除する

  1. ローカルマシンで、ブラウザタブを更新して審査担当者のウェブページから存在する音声文字変換テキストを消去します。

  2. Cloud Shell で、音声クライアントを再起動します。

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    

    審査担当者のページに音声文字変換テキストが表示されます。

  3. 他の Cloud Shell タブに切り替えます。

  4. Ingestor Pod を削除します。

    python3 deleter.py --applabel ingestor --iterations 5 --delay 15
    

    このスクリプトは、Kubernetes コントロール プレーンにクエリを実行して、すべての Ingestor Pod の名前を取得し、ランダムに選択した Pod を削除します。このコマンドは、Pod を 5 回削除し、イテレーションごとに 15 秒待機します。

    このスクリプトは、削除する Ingestor Pod をランダムに選択するため、音声クライアントが接続されている Pod は約半分しか削除されません。音声クライアントが接続されていない Pod を削除しても影響はありません。

  5. 審査担当者のウェブページをモニタリングします。Pod が削除されたとしても、音声文字変換は長く中断せずにページへのストリーミングを継続します。

  6. 音声クライアントを実行している他の Cloud Shell タブに切り替えます。

    Ingestor Pod への接続が切断して再確立されるたびに、クライアントがメッセージを表示することを確認します。

  7. Ctrl+C キーを押すと、音声クライアントは停止します。

審査担当者の Pod を削除する

  1. ローカルマシンで、ブラウザタブを更新して審査担当者のウェブページから存在する音声文字変換テキストを消去します。

  2. Cloud Shell で、音声クライアントを再起動します。

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    

    審査担当者のウェブページに音声文字変換テキストが表示されます。

  3. 他の Cloud Shell タブに切り替えます。

  4. Reviewer Pod を削除します。

    python3 deleter.py --applabel reviewer --iterations 5 --delay 15
    

    このスクリプトは、Kubernetes コントロール プレーンにクエリを実行して、すべての Reviewer Pod の名前を取得し、ランダムに選択した Pod を削除します。このコマンドは、Pod を 5 回削除し、イテレーションごとに 15 秒待機します。

  5. 審査担当者のウェブページをモニタリングします。

    Pod が削除されたとしても、音声文字変換は長く中断せずにページへのストリーミングを継続します。接続先の Reviewer Pod の名前がページに表示されます。Pod が削除されるときと、別の Pod との接続が確立されるときは、このフィールドが変更されます。

    前と同様に、Reviewer Pod はランダムに選択されて削除されるため、審査担当者のウェブページが接続されている Pod の削除には約半分の時間しかかかりません。デモ用ウェブ クライアントが接続されていない Pod を削除しても、音声文字変換の配信には影響しません。

  6. 他の Cloud Shell タブに切り替え、Ctrl+C キーを押してオーディオ クライアントを停止します。

Memorystore for Redis のフェイルオーバーのテスト

アプリは高速なメモリ内ストレージ用に Memorystore for Redis を使用します。スタンダード ティアの Memorystore for Redis インスタンスを使用して、レプリケーションと自動フェイルオーバーで高可用性を提供します。スタンダード ティアのインスタンスは、プライマリとレプリカのペアとして自動的に構成されます。レプリカはスタンバイとして動作し、プライマリとは異なるゾーンに配置されます。プライマリに障害が発生した場合、リクエストはレプリカに自動的にリダイレクトされます。

このセクションでは、手動フェイルオーバーを開始して Memorystore for Redis フェイルオーバーの動作をテストします。Memorystore for Redis サービスがレプリカをプライマリに昇格させている間、Memorystore for Redis インスタンスは一時的に使用できなくなります。つまり、フェイルオーバー中は音声文字変換が停止されます。

  1. ローカルマシンで、ブラウザタブを更新して審査担当者のウェブページから存在する音声文字変換テキストを消去します。
  2. Cloud Shell で、音声クライアントを再起動して音声ストリーミングを開始します。

    python audio_client.py --targetip $INGEST_IP \
        --file humptydumpty.wav
    
  3. 他の Cloud Shell タブで、Memorystore for Redis の手動フェイルオーバーを開始し、フェイルオーバーを続行することを選択します。

    gcloud redis instances failover redis-captions \
        --region us-central1 --project $PROJECT_ID
    
  4. 審査担当者のウェブページで音声文字変換の出力を確認します。

    Memorystore が使用できないことを示す [REDIS-FAILOVER] 通知が表示されます。予想どおりに、レプリカがプライマリに昇格する間は音声文字変換は停止します。このプロセスが完了すると、バッファリングされた音声データが処理され、音声文字変換が再開されます。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

プロジェクトの削除

  1. Cloud Console で [リソースの管理] ページに移動します。

    [リソースの管理] ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ