AWS lambdaで英語の音声ファイルを日本語のテキストに翻訳する

やりたいこと

以下の画像のような流れで英語の音声ファイルを日本語のテキストに翻訳したい。
f:id:Tk24:20200311111732p:plain

前回書いた記事で作成した機能を組み合わせたような形になります。

①英語の音声ファイルを手動でS3のinputバケットへアップロード
②inputバケットにファイルがアップロードされたことを検知し、文字起こし用Lambdaが実行される
Amazon Transcribeが実行され、音声ファイルから文字起こしファイルを作成します
④文字起こし結果をoutput用バケットに格納する
⑤output用バケットにファイルが作成されたことを検知し、翻訳用Lambdaが実行される
⑥翻訳結果をtranslate用バケットに格納する

構築

必要なバケットを準備

input用とoutput用のバケットは、前回作成しているので今回はtranslate用バケットのみ作成します。
※作成方法自体は、全てのバケット共通です。

こいつですね。

f:id:Tk24:20200311112236p:plain

1.S3のコンソール画面に移動します

2.バケットの作成をクリックします
f:id:Tk24:20200311114244j:plain

3.バケットリージョンを設定する1
f:id:Tk24:20200311114413j:plain

4.画面左下の作成をクリックします

文字起こし用Lambdaの準備

文字起こし用のLambdaは、前回作成した以下のLambdaを使用します。

こいつですね。

f:id:Tk24:20200311112346p:plain

import json
import urllib.parse
import boto3
import datetime

s3 = boto3.client('s3')
transcribe = boto3.client('transcribe')

def lambda_handler(event, context):
  #バケット名を取得
  bucket = event['Records'][0]['s3']['bucket']['name']
  #オブジェクトのキーを取得
  key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
  try:
    transcribe.start_transcription_job(
      #文字起こしのオブジェクト名を作成
      TranscriptionJobName= datetime.datetime.now().strftime("%Y%m%d%H%M%S") + '_Transcription',
      LanguageCode='en-US',
      #文字起こし用の音声ファイルを取得
      Media={
        'MediaFileUri': 'https://s3.ap-northeast-1.amazonaws.com/' + bucket + '/' + key
      },
      #作成したファイルを保存するバケット
      OutputBucketName=<文字起こしファイルの保存用バケット>
    )
  except Exception as e:
    print(e)
    print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
    raise e

Amazon Transcribeを使用し、音声を文字起こしします。
ちなみに、現在Amazon Transcribeに対応している言語は以下になります。

https://docs.aws.amazon.com/transcribe/latest/dg/what-is-transcribe.html

S3のinput用バケットがトリガーになっていることを確認し、完了です。

f:id:Tk24:20200311115152j:plain

翻訳用lambdaの作成

今回のメインですね。

f:id:Tk24:20200311112444p:plain

1. Lambdaのコンソールに移動します

2. 関数を作成をクリックします
f:id:Tk24:20200220115728j:plain

3. 設計図の使用にチェックを入れ、フィルターにS3と入力します
f:id:Tk24:20200311115548j:plain

4. 表示されたs3-get-object-pythonをクリックし、最下行の設定をクリックします
f:id:Tk24:20200311115840j:plain

5. 関数名ロール名を入力し、ポリシーテンプレートからAmazon S3 オブジェクトの読み取り専用アクセス権限を選択します
f:id:Tk24:20200311120039j:plain

6. バケットで自分で作成したoutput用バケットを選択します
f:id:Tk24:20200311120213j:plain

7. 最下行の関数の作成をクリックします

8. 表示された関数コードを以下のコードに変更します
f:id:Tk24:20200311120446j:plain

import json
import urllib.parse
import boto3
import datetime

print('Loading function')

s3 = boto3.client('s3')

def lambda_handler(event, context):
    #バケット名を取得
    bucket = event['Records'][0]['s3']['bucket']['name']
    #オブジェクトのキーを取得
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')

    try:
        translate = boto3.client('translate')
        #翻訳前のオブジェクトを取得
        input_text = s3.get_object(Bucket = bucket, Key = key)
        #jsonファイル内の翻訳対象が含まれるBodyのみを抜粋
        input_text = json.loads(input_text["Body"].read().decode('utf-8'))

        #さらに翻訳対象絞り込み、英語から日本語に変換
        response = translate.translate_text(
            Text=input_text["results"]["transcripts"][0]["transcript"],
            SourceLanguageCode="en",
            TargetLanguageCode="ja"
            )

    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e

    #作成したファイルを保存するオブジェクト名
    TranslateJobName= datetime.datetime.now().strftime("%Y%m%d%H%M%S") + '_Translate'
    #作成したファイルを保存するバケット名
    OutputBucketName=<翻訳ファイルの保存用バケット>
    #オブジェクトの内容
    output_text = response.get('TranslatedText')
    #翻訳した内容をtranslate用バケットに保存
    response = s3.put_object(Bucket=OutputBucketName, Key=TranslateJobName, Body=output_text.encode())
    
    return {
        'statusCode': 200,
        'body': json.dumps({
        'output_text': output_text
        })
    }

9. 実行ロールの設定を変更します
IAM コンソールで <設定したロール名>ロールを表示します。をクリックします
f:id:Tk24:20200311132236j:plain

ポリシーをアッタッチしますをクリックします
f:id:Tk24:20200311132332j:plain

以下のポリシーを検索し、左側にチェックを入れ、右下のポリシーをアタッチをクリックします
TranslateFullAccessAmazonS3FullAccess

f:id:Tk24:20200311132512j:plain

以上で設定は完了(のはず)です。

実践

では、実際に試してみます。 使用する音声ファイルは、前回と同じAmazon Pollyのサンプルを使用します。

https://d1.awsstatic.com/product-marketing/Polly/HelloEnglish-Joanna.0aa7a6dc7f1de9ac48769f366c6f447f9051db57.mp3

1. 音声ファイルをinput用のS3バケットにアップロードします。
f:id:Tk24:20200311133444j:plain

2. Amazon Transcribeの画面を確認し、ジョブが実行されていることを確認します。
f:id:Tk24:20200311132833j:plain

3. output用のS3バケットに文字起し結果のファイルが作成されていることを確認します
f:id:Tk24:20200311133457j:plain

4. 少し待ち、translate用バケットにファイルが新規作成されていることを確認します
f:id:Tk24:20200311133509j:plain

5. ファイルをダウンロードし、中身が
こんにちは。 外国語を話せますか。 一つの言語では十分ではありません。
となっていれば成功です!

もし、上手くいかない場合は、被疑箇所のLambdaのモニタリングCloudWatch Logs Insightsから実行結果ログを確認し、問題を特定してください。

以上です。


  1. リージョンはlambdaと同じにする必要があります