このハンズオンでは、AWSのサーバレスサービスを活用して、ローカルのテキストファイルをアップロードし、翻訳・音声化するシステムを構築します。
以下のAWSサービスを使用します。
Positive : 本ハンズオンは初心者向けの内容です。AWSの基本的な操作ができれば問題ありません。
Negative : 本ハンズオンで作成するリソースには料金が発生する場合があります。ハンズオン終了後は必ずリソースを削除してください。
Codespace のターミナルで以下のコマンドを実行します。
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install rm -rf awscliv2.zip aws/ aws --version
aws configure
項目 | 値 |
AWS Access Key ID | 管理者から払い出されたキー |
AWS Secret Access Key | 管理者から払い出されたシークレット |
Default region name |
|
Default output format |
|
aws sts get-caller-identity
Negative : アクセスキーをGitリポジトリにコミットしないよう注意してください。
テキストファイルをアップロードするためのS3バケットを作成します。
以下の設定でバケットを作成します。
項目 | 値 |
バケット名 |
|
AWSリージョン |
|
その他設定 | デフォルトのまま |
翻訳結果と音声ファイルを格納するS3バケットを作成します。
同様の手順で以下の設定のバケットを作成します。
項目 | 値 |
バケット名 |
|
AWSリージョン |
|
その他設定 | デフォルトのまま |
Positive : S3バケット名はグローバルで一意である必要があります。アカウントIDを含めることで重複を避けましょう。
Lambda関数がS3、Translate、Pollyにアクセスするためのロールを作成します。
以下の設定でロールを作成します。
項目 | 値 |
信頼されたエンティティ | AWS のサービス |
ユースケース | Lambda |
ロール名 |
|
以下のポリシーをアタッチします。
AmazonS3FullAccess
AmazonTranslateFullAccess
AmazonPollyFullAccess
CloudWatchLogsFullAccess
Negative : 本ハンズオンでは簡易化のためFullAccessポリシーを使用しますが、本番環境では最小権限の原則に基づいたポリシーを設定してください。
同様の手順で、Step Functions用のロールを作成します。
項目 | 値 |
信頼されたエンティティ | AWS のサービス |
ユースケース | Step Functions |
ロール名 |
|
以下のポリシーをアタッチします。
AWSLambda_FullAccess
CloudWatchLogsFullAccess
項目 | 値 |
関数名 |
|
ランタイム | Python 3.12 |
実行ロール |
|
以下のコードを入力します。
import json
import boto3
import urllib.parse
s3 = boto3.client('s3')
def lambda_handler(event, context):
"""S3からテキストファイルを読み取る"""
bucket = event['bucket']
key = event['key']
# S3からファイルを取得
response = s3.get_object(Bucket=bucket, Key=key)
text = response['Body'].read().decode('utf-8')
return {
'statusCode': 200,
'bucket': bucket,
'key': key,
'text': text,
'source_language': 'ja'
}
新しいLambda関数を作成します。
項目 | 値 |
関数名 |
|
ランタイム | Python 3.12 |
実行ロール |
|
以下のコードを入力します。
import json
import boto3
translate = boto3.client('translate')
def lambda_handler(event, context):
"""テキストを英語に翻訳する"""
text = event['text']
source_language = event.get('source_language', 'ja')
target_language = 'en'
# Amazon Translateで翻訳
response = translate.translate_text(
Text=text,
SourceLanguageCode=source_language,
TargetLanguageCode=target_language
)
translated_text = response['TranslatedText']
return {
'statusCode': 200,
'bucket': event['bucket'],
'key': event['key'],
'original_text': text,
'translated_text': translated_text,
'source_language': source_language,
'target_language': target_language
}
Positive : Amazon Translateは多くの言語ペアに対応しています。source_languageとtarget_languageを変更することで、様々な言語間の翻訳が可能です。
新しいLambda関数を作成します。
項目 | 値 |
関数名 |
|
ランタイム | Python 3.12 |
実行ロール |
|
タイムアウト | 60秒(デフォルトの3秒から変更) |
以下のコードを入力します。
import json
import boto3
from datetime import datetime
polly = boto3.client('polly')
s3 = boto3.client('s3')
def lambda_handler(event, context):
"""翻訳されたテキストを音声に変換してS3に保存する"""
translated_text = event['translated_text']
output_bucket = event['bucket'].replace('input', 'output')
original_key = event['key']
# ファイル名を生成
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
output_key_text = f"translated/{timestamp}_{original_key}"
output_key_audio = f"audio/{timestamp}_{original_key.replace('.txt', '.mp3')}"
# 翻訳テキストをS3に保存
s3.put_object(
Bucket=output_bucket,
Key=output_key_text,
Body=translated_text.encode('utf-8'),
ContentType='text/plain'
)
# Amazon Pollyで音声合成
response = polly.synthesize_speech(
Text=translated_text,
OutputFormat='mp3',
VoiceId='Joanna',
Engine='neural'
)
# 音声ファイルをS3に保存
audio_stream = response['AudioStream'].read()
s3.put_object(
Bucket=output_bucket,
Key=output_key_audio,
Body=audio_stream,
ContentType='audio/mpeg'
)
return {
'statusCode': 200,
'output_bucket': output_bucket,
'translated_text_key': output_key_text,
'audio_key': output_key_audio,
'message': '翻訳テキストと音声ファイルの保存が完了しました'
}
以下のASL(Amazon States Language)を入力します。
{
"Comment": "テキストファイルの翻訳・音声化ワークフロー",
"StartAt": "ReadText",
"States": {
"ReadText": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:{アカウントID}:function:handson-read-text",
"Next": "TranslateText",
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Next": "HandleError"
}
]
},
"TranslateText": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:{アカウントID}:function:handson-translate-text",
"Next": "TextToSpeech",
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Next": "HandleError"
}
]
},
"TextToSpeech": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:{アカウントID}:function:handson-text-to-speech",
"Next": "SuccessState",
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Next": "HandleError"
}
]
},
"SuccessState": {
"Type": "Succeed"
},
"HandleError": {
"Type": "Fail",
"Error": "ProcessingError",
"Cause": "ワークフローの実行中にエラーが発生しました"
}
}
}
Negative : {アカウントID} は自分のAWSアカウントIDに置き換えてください。
項目 | 値 |
ステートマシン名 |
|
実行ロール |
|
ログ記録 | すべてのログ |
S3にテキストファイルがアップロードされた際に、自動的にStep Functionsを実行するよう設定します。
Positive : S3イベント通知からStep Functionsを直接起動するには、Amazon EventBridge経由で設定することもできます。
次に、EventBridgeでルールを作成します。
項目 | 値 |
ルール名 |
|
イベントバス | default |
ルールタイプ | イベントパターンを持つルール |
{
"source": ["aws.s3"],
"detail-type": ["Object Created"],
"detail": {
"bucket": {
"name": ["handson-input-{アカウントID}"]
},
"object": {
"key": [{
"suffix": ".txt"
}]
}
}
}
handson-translate-workflow を指定しますローカルにテスト用のテキストファイルを作成します。
echo "こんにちは。今日はAWSのサーバレスサービスを使ったハンズオンを行います。楽しんでいきましょう。" > test.txt
AWS CLIを使ってファイルをアップロードします。
aws s3 cp test.txt s3://handson-input-{アカウントID}/test.txt
translated/ フォルダ - 翻訳されたテキストファイルaudio/ フォルダ - 音声ファイル(.mp3)aws s3 ls s3://handson-output-{アカウントID}/audio/
aws s3 cp s3://handson-output-{アカウントID}/audio/{生成されたファイル名}.mp3 ./output.mp3
ダウンロードしたMP3ファイルを再生して、英語の音声が出力されることを確認します。
Positive : ワークフローがエラーになった場合は、Step Functionsの実行履歴からエラーの詳細を確認してください。Lambda関数のCloudWatch Logsも参考になります。
ハンズオンが完了したら、以下のリソースを削除して料金の発生を防ぎましょう。
削除順序は以下の通りです。
handson-s3-to-stepfunctions を削除handson-translate-workflow を削除handson-read-texthandson-translate-texthandson-text-to-speechhandson-input-{アカウントID}handson-output-{アカウントID}handson-lambda-rolehandson-stepfunctions-roleaws s3 rm s3://handson-input-{アカウントID} --recursive
aws s3 rm s3://handson-output-{アカウントID} --recursive
aws s3 rb s3://handson-input-{アカウントID}
aws s3 rb s3://handson-output-{アカウントID}
Negative : リソースの削除を忘れると、意図しない料金が発生する可能性があります。必ず全てのリソースを削除してください。
このハンズオンでは以下のことを学びました。
[AWS Lambda ドキュメント](https://docs.aws.amazon.com/ja_jp/lambda/)
[AWS Step Functions ドキュメント](https://docs.aws.amazon.com/ja_jp/step-functions/)
[Amazon Translate ドキュメント](https://docs.aws.amazon.com/ja_jp/translate/)
[Amazon Polly ドキュメント](https://docs.aws.amazon.com/ja_jp/polly/)