0
0

「AWS Hands-on for Beginners Serverless #3 AWS Lambda と AWS AI Services を組み合わせて作る音声文字起こし & 感情分析パイプライン」をAWS CLIでやってみる

Posted at

上記、「AWS Hands-on for Beginners Serverless #3 AWS Lambda と AWS AI Services を組み合わせて作る音声文字起こし & 感情分析パイプライン」 をAWS CLIでやってみる

image.png
ハンズオンから引用

03 S3 トリガーで Lambda ファンクションを起動する

S3バケット作成

変数

コマンド
# バケット名
date_var=$(date +%Y%m%d) \
&& echo ${date_var}
S3_BUCKET_NAME="h4b-serverless-3-input-${date_var}" \
&& echo ${S3_BUCKET_NAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # バケット名
[cloudshell-user@ip-10-132-73-220 ~]$ date_var=$(date +%Y%m%d) \
> && echo ${date_var}
20240929
[cloudshell-user@ip-10-132-73-220 ~]$ S3_BUCKET_NAME="h4b-serverless-3-input-${date_var}" \
> && echo ${S3_BUCKET_NAME}
h4b-serverless-3-input-20240929

S3バケット作成

コマンド
# S3バケット作成
aws s3 mb s3://${S3_BUCKET_NAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケット作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 mb s3://${S3_BUCKET_NAME}
make_bucket: h4b-serverless-3-input-20240929

Lambda関数作成

変数

コマンド
# 関数名
LAMBDA_FUNCTION_NAME="transcribe-function" \
&& echo ${LAMBDA_FUNCTION_NAME}

# IAMポリシー名1
IAM_POLICY_NAME_1="AWSLambdaBasicExecutionRole-${LAMBDA_FUNCTION_NAME}" \
&& echo ${IAM_POLICY_NAME_1}

# IAMポリシー名2
IAM_POLICY_NAME_2="AWSLambdaS3ExecutionRole-${LAMBDA_FUNCTION_NAME}" \
&& echo ${IAM_POLICY_NAME_2}

# IAMロール名
IAM_ROLE_NAME="${LAMBDA_FUNCTION_NAME}-role" \
&& echo ${IAM_ROLE_NAME}

# ランタイム
LAMBDA_RUNTIME="python3.10" \
&& echo ${LAMBDA_RUNTIME}

# アカウントID
ACCOUNT_ID="999999999999" \
&& echo ${ACCOUNT_ID}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 関数名
[cloudshell-user@ip-10-132-73-220 ~]$ LAMBDA_FUNCTION_NAME="transcribe-function" \
> && echo ${LAMBDA_FUNCTION_NAME}
transcribe-function
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMポリシー名1
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_NAME_1="AWSLambdaBasicExecutionRole-${LAMBDA_FUNCTION_NAME}" \
> && echo ${IAM_POLICY_NAME_1}
AWSLambdaBasicExecutionRole-transcribe-function
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMポリシー名2
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_NAME_2="AWSLambdaS3ExecutionRole-${LAMBDA_FUNCTION_NAME}" \
> && echo ${IAM_POLICY_NAME_2}
AWSLambdaS3ExecutionRole-transcribe-function
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロール名
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_ROLE_NAME="${LAMBDA_FUNCTION_NAME}-role" \
> && echo ${IAM_ROLE_NAME}
transcribe-function-role
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ランタイム
[cloudshell-user@ip-10-132-73-220 ~]$ LAMBDA_RUNTIME="python3.10" \
> && echo ${LAMBDA_RUNTIME}
python3.10
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アカウントID
[cloudshell-user@ip-10-132-73-220 ~]$ ACCOUNT_ID="999999999999" \
> && echo ${ACCOUNT_ID}
999999999999

IAMポリシー作成

AWSLambdaBasicExecutionRole

コマンド
# AWSLambdaBasicExecutionRole
# ポリシードキュメントの作成
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:log-group:/aws/lambda/${LAMBDA_FUNCTION_NAME}:*"
            ]
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${IAM_POLICY_NAME_1} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
IAM_POLICY_ARN_1=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${IAM_POLICY_NAME_1}'].Arn" \
        --output text
) \
&& echo ${IAM_POLICY_ARN_1}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # AWSLambdaBasicExecutionRole
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシードキュメントの作成
[cloudshell-user@ip-10-132-73-220 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": "logs:CreateLogGroup",
>             "Resource": "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "logs:CreateLogStream",
>                 "logs:PutLogEvents"
>             ],
>             "Resource": [
>                 "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:log-group:/aws/lambda/${LAMBDA_FUNCTION_NAME}:*"
>             ]
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:ap-northeast-1:999999999999:*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/lambda/transcribe-function:*" ] } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:999999999999:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/lambda/transcribe-function:*"
            ]
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam create-policy \
>     --policy-name ${IAM_POLICY_NAME_1} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "AWSLambdaBasicExecutionRole-transcribe-function",
        "PolicyId": "ANPAWFKRCMKOVTQGI5MZX",
        "Arn": "arn:aws:iam::999999999999:policy/AWSLambdaBasicExecutionRole-transcribe-function",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-29T07:39:15+00:00",
        "UpdateDate": "2024-09-29T07:39:15+00:00"
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ARN取得
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_ARN_1=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${IAM_POLICY_NAME_1}'].Arn" \
>         --output text
> ) \
> && echo ${IAM_POLICY_ARN_1}
arn:aws:iam::999999999999:policy/AWSLambdaBasicExecutionRole-transcribe-function

AWSLambdaS3ExecutionRole

コマンド
# AWSLambdaS3ExecutionRole
# ポリシードキュメントの作成
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${IAM_POLICY_NAME_2} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
IAM_POLICY_ARN_2=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${IAM_POLICY_NAME_2}'].Arn" \
        --output text
) \
&& echo ${IAM_POLICY_ARN_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # AWSLambdaS3ExecutionRole
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシードキュメントの作成
[cloudshell-user@ip-10-132-73-220 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "s3:GetObject"
>             ],
>             "Resource": "arn:aws:s3:::*"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::*" } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam create-policy \
>     --policy-name ${IAM_POLICY_NAME_2} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "AWSLambdaS3ExecutionRole-transcribe-function",
        "PolicyId": "ANPAWFKRCMKO4VOZM3AAK",
        "Arn": "arn:aws:iam::999999999999:policy/AWSLambdaS3ExecutionRole-transcribe-function",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-29T07:39:46+00:00",
        "UpdateDate": "2024-09-29T07:39:46+00:00"
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ARN取得
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_ARN_2=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${IAM_POLICY_NAME_2}'].Arn" \
>         --output text
> ) \
> && echo ${IAM_POLICY_ARN_2}
arn:aws:iam::999999999999:policy/AWSLambdaS3ExecutionRole-transcribe-function

IAMロール作成

コマンド
# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --role-name ${IAM_ROLE_NAME} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
IAM_ROLE_ARN=$(
    aws iam get-role \
        --role-name ${IAM_ROLE_NAME} \
        --query 'Role.Arn' --output text
) \
&& echo ${IAM_ROLE_ARN}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME} \
    --policy-arn ${IAM_POLICY_ARN_1}

aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME} \
    --policy-arn ${IAM_POLICY_ARN_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-73-220 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "lambda.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam create-role \
>     --role-name ${IAM_ROLE_NAME} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/",
        "RoleName": "transcribe-function-role",
        "RoleId": "AROAWFKRCMKOUX4DN3SXQ",
        "Arn": "arn:aws:iam::999999999999:role/transcribe-function-role",
        "CreateDate": "2024-09-29T07:40:18+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ARN取得
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_ROLE_ARN=$(
>     aws iam get-role \
>         --role-name ${IAM_ROLE_NAME} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${IAM_ROLE_ARN}
arn:aws:iam::999999999999:role/transcribe-function-role
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME} \
>     --policy-arn ${IAM_POLICY_ARN_1}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME} \
>     --policy-arn ${IAM_POLICY_ARN_2}

Lambdaソースコード

コマンド
cat << EOF > lambda_function.py
import json
import urllib.parse
import boto3

print('Loading function')

s3 = boto3.client('s3')


def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    try:
        response = s3.get_object(Bucket=bucket, Key=key)
        print("CONTENT TYPE: " + response['ContentType'])
        return response['ContentType']
    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
EOF

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat << EOF > lambda_function.py
> import json
> import urllib.parse
> import boto3
> 
> print('Loading function')
> 
> s3 = boto3.client('s3')
> 
> 
> def lambda_handler(event, context):
>     #print("Received event: " + json.dumps(event, indent=2))
> 
>     # Get the object from the event and show its content type
>     bucket = event['Records'][0]['s3']['bucket']['name']
>     key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
>     try:
>         response = s3.get_object(Bucket=bucket, Key=key)
>         print("CONTENT TYPE: " + response['ContentType'])
>         return response['ContentType']
>     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
> EOF

デプロイパッケージの作成

コマンド
zip function.zip lambda_function.py

出力
[cloudshell-user@ip-10-132-73-220 ~]$ zip function.zip lambda_function.py
  adding: lambda_function.py (deflated 45%)

Lambda関数の作成

コマンド
# Lambda関数の作成
aws lambda create-function \
    --function-name ${LAMBDA_FUNCTION_NAME} \
    --role ${IAM_ROLE_ARN} \
    --zip-file fileb://function.zip \
    --runtime ${LAMBDA_RUNTIME} \
    --handler lambda_function.lambda_handler \

# ARNの取得
LAMBDA_FUNCTION_ARN=$(
    aws lambda list-functions \
        --query "Functions[?FunctionName=='${LAMBDA_FUNCTION_NAME}'].FunctionArn" \
        --output text
) \
&& echo ${LAMBDA_FUNCTION_ARN}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # Lambda関数の作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda create-function \
>     --function-name ${LAMBDA_FUNCTION_NAME} \
>     --role ${IAM_ROLE_ARN} \
>     --zip-file fileb://function.zip \
>     --runtime ${LAMBDA_RUNTIME} \
>     --handler lambda_function.lambda_handler \
> 
{
    "FunctionName": "transcribe-function",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function",
    "Runtime": "python3.10",
    "Role": "arn:aws:iam::999999999999:role/transcribe-function-role",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 618,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-09-29T07:41:42.633+0000",
    "CodeSha256": "NBLXCaelqN6abvXytUmpDVs/XdWxOBY5b6yZTUgmMuE=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "33913ed1-07cd-4240-bea8-caa0d0f8ca87",
    "State": "Pending",
    "StateReason": "The function is being created.",
    "StateReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
    },
    "RuntimeVersionConfig": {
        "RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086"
    },
    "LoggingConfig": {
        "LogFormat": "Text",
        "LogGroup": "/aws/lambda/transcribe-function"
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ # ARNの取得
[cloudshell-user@ip-10-132-73-220 ~]$ LAMBDA_FUNCTION_ARN=$(
>     aws lambda list-functions \
>         --query "Functions[?FunctionName=='${LAMBDA_FUNCTION_NAME}'].FunctionArn" \
>         --output text
> ) \
> && echo ${LAMBDA_FUNCTION_ARN}
arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function

リソースベースのポリシーステートメント追加

コマンド
# リソースベースのポリシーステートメント追加
aws lambda add-permission \
    --function-name ${LAMBDA_FUNCTION_NAME} \
    --principal s3.amazonaws.com \
    --statement-id S3InvokePermission \
    --action "lambda:InvokeFunction" \
    --source-arn arn:aws:s3:::${S3_BUCKET_NAME} \
    --source-account ${ACCOUNT_ID}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # リソースベースのポリシーステートメント追加
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda add-permission \
>     --function-name ${LAMBDA_FUNCTION_NAME} \
>     --principal s3.amazonaws.com \
>     --statement-id S3InvokePermission \
>     --action "lambda:InvokeFunction" \
>     --source-arn arn:aws:s3:::${S3_BUCKET_NAME} \
>     --source-account ${ACCOUNT_ID}
{
    "Statement": "{\"Sid\":\"S3InvokePermission\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function\",\"Condition\":{\"StringEquals\":{\"AWS:SourceAccount\":\"999999999999\"},\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::h4b-serverless-3-input-20240929\"}}}"
}

イベント通知設定用JSON

コマンド
# イベント通知設定用JSON
S3_NOTIFICATION_CONFIGURATION=$(cat << EOF
{
    "LambdaFunctionConfigurations": [
        {
            "LambdaFunctionArn": "${LAMBDA_FUNCTION_ARN}",
            "Events": ["s3:ObjectCreated:*"]
        }
    ]
}
EOF
) \
&& echo ${S3_NOTIFICATION_CONFIGURATION}

# JSONフォーマットの確認
echo ${S3_NOTIFICATION_CONFIGURATION} | python -m json.tool

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # イベント通知設定用JSON
[cloudshell-user@ip-10-132-73-220 ~]$ S3_NOTIFICATION_CONFIGURATION=$(cat << EOF
> {
>     "LambdaFunctionConfigurations": [
>         {
>             "LambdaFunctionArn": "${LAMBDA_FUNCTION_ARN}",
>             "Events": ["s3:ObjectCreated:*"]
>         }
>     ]
> }
> EOF
> ) \
> && echo ${S3_NOTIFICATION_CONFIGURATION}
{ "LambdaFunctionConfigurations": [ { "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function", "Events": ["s3:ObjectCreated:*"] } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${S3_NOTIFICATION_CONFIGURATION} | python -m json.tool
{
    "LambdaFunctionConfigurations": [
        {
            "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function",
            "Events": [
                "s3:ObjectCreated:*"
            ]
        }
    ]
}

S3 バケットにイベント通知を設定して Lambda をトリガー

コマンド
aws s3api put-bucket-notification-configuration \
    --bucket ${S3_BUCKET_NAME} \
    --notification-configuration "${S3_NOTIFICATION_CONFIGURATION}"

出力
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api put-bucket-notification-configuration \
>     --bucket ${S3_BUCKET_NAME} \
>     --notification-configuration "${S3_NOTIFICATION_CONFIGURATION}"

S3にファイルをアップロード

コマンド
# アップロードファイル名
UPLOAD_FILENAME="h4b-serverless-3.mp3" \
&& echo ${UPLOAD_FILENAME}

# アップロード
aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ UPLOAD_FILENAME="h4b-serverless-3.mp3" \
> && echo ${UPLOAD_FILENAME}
h4b-serverless-3.mp3
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/
upload: ./h4b-serverless-3.mp3 to s3://h4b-serverless-3-input-20240929/h4b-serverless-3.mp3

CloudWatchロググループ確認

コマンド
# 最新のログストリームを取得
LATEST_LOG_STREAM=$(
    aws logs describe-log-streams \
        --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
        --order-by LastEventTime \
        --descending \
        --limit 1 \
        --query 'logStreams[0].logStreamName' \
        --output text
) \
&& echo ${LATEST_LOG_STREAM}

# ログの確認
aws logs get-log-events \
    --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
    --log-stream-name ${LATEST_LOG_STREAM} \
    --no-cli-pager

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 最新のログストリームを取得
[cloudshell-user@ip-10-132-73-220 ~]$ LATEST_LOG_STREAM=$(
>     aws logs describe-log-streams \
>         --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
>         --order-by LastEventTime \
>         --descending \
>         --limit 1 \
>         --query 'logStreams[0].logStreamName' \
>         --output text
> ) \
> && echo ${LATEST_LOG_STREAM}
2024/09/29/[$LATEST]74551e5835134c22a39d83ea543656c0
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ログの確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws logs get-log-events \
>     --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
>     --log-stream-name ${LATEST_LOG_STREAM} \
>     --no-cli-pager
{
    "events": [
        {
            "timestamp": 1727596189995,
            "message": "INIT_START Runtime Version: python:3.10.v38\tRuntime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086\n",
            "ingestionTime": 1727596195784
        },
        {
            "timestamp": 1727596190274,
            "message": "Loading function\n",
            "ingestionTime": 1727596195784
        },
        {
            "timestamp": 1727596190474,
            "message": "START RequestId: 241f7b6e-8c03-4bcc-835f-ad6048ebb83c Version: $LATEST\n",
            "ingestionTime": 1727596195784
        },
        {
            "timestamp": 1727596190736,
            "message": "CONTENT TYPE: audio/mpeg\n",
            "ingestionTime": 1727596195784
        },
        {
            "timestamp": 1727596190739,
            "message": "END RequestId: 241f7b6e-8c03-4bcc-835f-ad6048ebb83c\n",
            "ingestionTime": 1727596195784
        },
        {
            "timestamp": 1727596190739,
            "message": "REPORT RequestId: 241f7b6e-8c03-4bcc-835f-ad6048ebb83c\tDuration: 264.96 ms\tBilled Duration: 265 ms\tMemory Size: 128 MB\tMax Memory Used: 78 MB\tInit Duration: 478.05 ms\t\n",
            "ingestionTime": 1727596195784
        }
    ],
    "nextForwardToken": "f/38526682455622548841445603785287162832960337203410239493/s",
    "nextBackwardToken": "b/38526682439030794413738820167984588438109956242960809984/s"
}

Lambda関数更新

ソースコード更新

コマンド
cat << EOF > lambda_function.py
import json
import urllib.parse
import boto3

print('Loading function')

s3 = boto3.client('s3')


def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    try:
        response = s3.get_object(Bucket=bucket, Key=key)
        print("CONTENT TYPE: " + response['ContentType'])
        return response['ContentType']
    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
EOF

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat << EOF > lambda_function.py
> import json
> import urllib.parse
> import boto3
> 
> print('Loading function')
> 
> s3 = boto3.client('s3')
> 
> 
> def lambda_handler(event, context):
>     print("Received event: " + json.dumps(event, indent=2))
> 
>     # Get the object from the event and show its content type
>     bucket = event['Records'][0]['s3']['bucket']['name']
>     key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
>     try:
>         response = s3.get_object(Bucket=bucket, Key=key)
>         print("CONTENT TYPE: " + response['ContentType'])
>         return response['ContentType']
>     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
> EOF

デプロイパッケージの作成

コマンド
zip function.zip lambda_function.py

出力
[cloudshell-user@ip-10-132-73-220 ~]$ zip function.zip lambda_function.py
updating: lambda_function.py (deflated 45%)

Lambda関数の更新

コマンド
aws lambda update-function-code \
    --function-name ${LAMBDA_FUNCTION_NAME}  \
    --zip-file fileb://function.zip

出力
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda update-function-code \
>     --function-name ${LAMBDA_FUNCTION_NAME}  \
>     --zip-file fileb://function.zip
{
    "FunctionName": "transcribe-function",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function",
    "Runtime": "python3.10",
    "Role": "arn:aws:iam::999999999999:role/transcribe-function-role",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 618,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-09-29T07:52:18.000+0000",
    "CodeSha256": "3CtjLOpsg1IZuO8J3ogj+Zz0rZ1ucVpqPsK0mRt9FJE=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "ad218fa8-6fbe-4fef-8ca7-a006fb2cf68b",
    "State": "Active",
    "LastUpdateStatus": "InProgress",
    "LastUpdateStatusReason": "The function is being created.",
    "LastUpdateStatusReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
    },
    "RuntimeVersionConfig": {
        "RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086"
    },
    "LoggingConfig": {
        "LogFormat": "Text",
        "LogGroup": "/aws/lambda/transcribe-function"
    }
}

S3にファイルをアップロード

コマンド
# アップロードファイル名
UPLOAD_FILENAME="h4b-serverless-3.mp3" \
&& echo ${UPLOAD_FILENAME}

# アップロード
aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ UPLOAD_FILENAME="h4b-serverless-3.mp3" \
> && echo ${UPLOAD_FILENAME}
h4b-serverless-3.mp3
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/
upload: ./h4b-serverless-3.mp3 to s3://h4b-serverless-3-input-20240929/h4b-serverless-3.mp3

CloudWatchロググループ確認

コマンド
# 最新のログストリームを取得
LATEST_LOG_STREAM=$(
    aws logs describe-log-streams \
        --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
        --order-by LastEventTime \
        --descending \
        --limit 1 \
        --query 'logStreams[0].logStreamName' \
        --output text
) \
&& echo ${LATEST_LOG_STREAM}

# ログの確認
aws logs get-log-events \
    --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
    --log-stream-name ${LATEST_LOG_STREAM} \
    --no-cli-pager

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 最新のログストリームを取得
[cloudshell-user@ip-10-132-73-220 ~]$ LATEST_LOG_STREAM=$(
>     aws logs describe-log-streams \
>         --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
>         --order-by LastEventTime \
>         --descending \
>         --limit 1 \
>         --query 'logStreams[0].logStreamName' \
>         --output text
> ) \
> && echo ${LATEST_LOG_STREAM}
2024/09/29/[$LATEST]ee2126f3b66541cea630ee1bded27bfe
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ログの確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws logs get-log-events \
>     --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME} \
>     --log-stream-name ${LATEST_LOG_STREAM} \
>     --no-cli-pager
{
    "events": [
        {
            "timestamp": 1727596368082,
            "message": "INIT_START Runtime Version: python:3.10.v38\tRuntime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368333,
            "message": "Loading function\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368497,
            "message": "START RequestId: 50a0a849-744a-4a7b-8c34-bc5eaf5b5e09 Version: $LATEST\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "Received event: {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"Records\": [\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "{\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"eventVersion\": \"2.1\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"eventSource\": \"aws:s3\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"awsRegion\": \"ap-northeast-1\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"eventTime\": \"2024-09-29T07:52:46.894Z\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"eventName\": \"ObjectCreated:Put\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"userIdentity\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"principalId\": \"AWS:AIDAWFKRCMKOXV327GJV2\"\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "},\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"requestParameters\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"sourceIPAddress\": \"35.75.18.236\"\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "},\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"responseElements\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"x-amz-request-id\": \"74HCBPRQ5FWG2GKR\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"x-amz-id-2\": \"OmoMH73cInpv11HWqelmwdDUVMDnaqdxLldow+WiDu6pKaXIH1IcjPNPP/MysZlJ2PRk++qeile6Su9ZIRjMqYp06kgk2R6T\"\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "},\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"s3\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"s3SchemaVersion\": \"1.0\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"configurationId\": \"ZTVkNGE5MzItYmI4MS00ZWRjLWIyMmMtMzQzOTVhZjc5ODBh\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"bucket\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"name\": \"h4b-serverless-3-input-20240929\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"ownerIdentity\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"principalId\": \"A1N79N9DXMUVCN\"\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "},\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"arn\": \"arn:aws:s3:::h4b-serverless-3-input-20240929\"\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "},\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"object\": {\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"key\": \"h4b-serverless-3.mp3\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"size\": 27944,\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"eTag\": \"18fc7f0024c99b45f741d528d0411086\",\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "\"sequencer\": \"0066F9074ED6A76D3E\"\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "}\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "}\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "}\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "]\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368498,
            "message": "}\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368775,
            "message": "CONTENT TYPE: audio/mpeg\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368796,
            "message": "END RequestId: 50a0a849-744a-4a7b-8c34-bc5eaf5b5e09\n",
            "ingestionTime": 1727596376326
        },
        {
            "timestamp": 1727596368797,
            "message": "REPORT RequestId: 50a0a849-744a-4a7b-8c34-bc5eaf5b5e09\tDuration: 299.35 ms\tBilled Duration: 300 ms\tMemory Size: 128 MB\tMax Memory Used: 78 MB\tInit Duration: 414.32 ms\t\n",
            "ingestionTime": 1727596376326
        }
    ],
    "nextForwardToken": "f/38526686426448637401411299339116193659073992568340414507/s",
    "nextBackwardToken": "b/38526686410503604584461903792918155094130414091564417024/s"
}

04 Amazon Transcribe を使って文字起こしを試してみる

S3バケット作成

変数

コマンド
# バケット名
date_var=$(date +%Y%m%d) \
&& echo ${date_var}
S3_BUCKET_NAME_2="h4b-serverless-3-output-${date_var}" \
&& echo ${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # バケット名
[cloudshell-user@ip-10-132-73-220 ~]$ date_var=$(date +%Y%m%d) \
> && echo ${date_var}
20240929
[cloudshell-user@ip-10-132-73-220 ~]$ S3_BUCKET_NAME_2="h4b-serverless-3-output-${date_var}" \
> && echo ${S3_BUCKET_NAME_2}
h4b-serverless-3-output-20240929

S3バケット作成

コマンド
# S3バケット作成
aws s3 mb s3://${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケット作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 mb s3://${S3_BUCKET_NAME_2}
make_bucket: h4b-serverless-3-output-20240929

トランスクリプションジョブ作成

変数

コマンド
TRANSCRIPTION_JOB_NAME="Test-Job" \
&& echo ${TRANSCRIPTION_JOB_NAME}

TRANSCRIPTION_LANG_CODE="ja-JP" \
&& echo ${TRANSCRIPTION_LANG_CODE}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ TRANSCRIPTION_JOB_NAME="Test-Job" \
> && echo ${TRANSCRIPTION_JOB_NAME}
Test-Job
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ TRANSCRIPTION_LANG_CODE="ja-JP" \
> && echo ${TRANSCRIPTION_LANG_CODE}
ja-JP

トランスクリプションジョブ作成

コマンド
# トランスクリプションジョブ作成
aws transcribe start-transcription-job \
    --transcription-job-name "${TRANSCRIPTION_JOB_NAME}" \
    --language-code "${TRANSCRIPTION_LANG_CODE}" \
    --media MediaFileUri=s3://${S3_BUCKET_NAME}/${UPLOAD_FILENAME} \
    --output-bucket-name "${S3_BUCKET_NAME_2}"

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # トランスクリプションジョブ作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws transcribe start-transcription-job \
>     --transcription-job-name "${TRANSCRIPTION_JOB_NAME}" \
>     --language-code "${TRANSCRIPTION_LANG_CODE}" \
>     --media MediaFileUri=s3://${S3_BUCKET_NAME}/${UPLOAD_FILENAME} \
>     --output-bucket-name "${S3_BUCKET_NAME_2}"
{
    "TranscriptionJob": {
        "TranscriptionJobName": "Test-Job",
        "TranscriptionJobStatus": "IN_PROGRESS",
        "LanguageCode": "ja-JP",
        "Media": {
            "MediaFileUri": "s3://h4b-serverless-3-input-20240929/h4b-serverless-3.mp3"
        },
        "StartTime": "2024-09-29T16:55:31.505000+09:00",
        "CreationTime": "2024-09-29T16:55:31.482000+09:00"
    }
}

確認

コマンド
# 確認
aws transcribe get-transcription-job \
    --transcription-job-name "${TRANSCRIPTION_JOB_NAME}"

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws transcribe get-transcription-job \
>     --transcription-job-name "${TRANSCRIPTION_JOB_NAME}"
{
    "TranscriptionJob": {
        "TranscriptionJobName": "Test-Job",
        "TranscriptionJobStatus": "COMPLETED",
        "LanguageCode": "ja-JP",
        "MediaSampleRateHertz": 22050,
        "MediaFormat": "mp3",
        "Media": {
            "MediaFileUri": "s3://h4b-serverless-3-input-20240929/h4b-serverless-3.mp3"
        },
        "Transcript": {
            "TranscriptFileUri": "https://s3.ap-northeast-1.amazonaws.com/h4b-serverless-3-output-20240929/Test-Job.json"
        },
        "StartTime": "2024-09-29T16:55:31.505000+09:00",
        "CreationTime": "2024-09-29T16:55:31.482000+09:00",
        "CompletionTime": "2024-09-29T16:55:42.879000+09:00",
        "Settings": {
            "ChannelIdentification": false,
            "ShowAlternatives": false
        }
    }
}

S3バケット内のオブジェクトを確認

コマンド
aws s3api list-object-versions \
    --bucket ${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api list-object-versions \
>     --bucket ${S3_BUCKET_NAME_2}
{
    "Versions": [
        {
            "ETag": "\"d751713988987e9331980363e24189ce\"",
            "Size": 2,
            "StorageClass": "STANDARD",
            "Key": ".write_access_check_file.temp",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T07:55:32+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"40033c4f71ea9b9cc33b3201afd6c613\"",
            "Size": 1991,
            "StorageClass": "STANDARD",
            "Key": "Test-Job.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T07:55:43+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        }
    ],
    "RequestCharged": null
}

S3からファイルをダウンロード

コマンド
# ダウンロードファイル名
DOWNLOAD_FILENAME="Test-Job.json" \
&& echo ${DOWNLOAD_FILENAME}

# ダウンロード
aws s3 cp s3://${S3_BUCKET_NAME_2}/${DOWNLOAD_FILENAME} ./

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # ダウンロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ DOWNLOAD_FILENAME="Test-Job.json" \
> && echo ${DOWNLOAD_FILENAME}
Test-Job.json
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ダウンロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp s3://${S3_BUCKET_NAME_2}/${DOWNLOAD_FILENAME} ./
download: s3://h4b-serverless-3-output-20240929/Test-Job.json to ./Test-Job.json

ダウンロードしたファイルを確認

コマンド
cat ${DOWNLOAD_FILENAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat ${DOWNLOAD_FILENAME} 
{"jobName":"Test-Job","accountId":"999999999999","status":"COMPLETED","results":{"transcripts":[{"transcript":"半音順調ですか?手を動かすの楽しいですよ"}],"items":[{"id":0,"type":"pronunciation","alternatives":[{"confidence":"0.996","content":"半"}],"start_time":"0.1","end_time":"0.4"},{"id":1,"type":"pronunciation","alternatives":[{"confidence":"0.611","content":"音"}],"start_time":"0.409","end_time":"0.74"},{"id":2,"type":"pronunciation","alternatives":[{"confidence":"0.997","content":"順調"}],"start_time":"0.75","end_time":"1.179"},{"id":3,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"です"}],"start_time":"1.19","end_time":"1.5"},{"id":4,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"か"}],"start_time":"1.509","end_time":"1.73"},{"id":5,"type":"punctuation","alternatives":[{"confidence":"0.0","content":"?"}]},{"id":6,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"手"}],"start_time":"2.19","end_time":"2.339"},{"id":7,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"を"}],"start_time":"2.349","end_time":"2.5"},{"id":8,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"動かす"}],"start_time":"2.509","end_time":"3.059"},{"id":9,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"の"}],"start_time":"3.069","end_time":"3.21"},{"id":10,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"楽しい"}],"start_time":"3.4","end_time":"3.92"},{"id":11,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"です"}],"start_time":"3.93","end_time":"4.219"},{"id":12,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"よ"}],"start_time":"4.23","end_time":"4.519"}],"audio_segments":[{"id":0,"transcript":"半音順調ですか?手を動かすの楽しいですよ","start_time":"0.0","end_time":"4.63","items":[0,1,2,3,4,5,6,7,8,9,10,11,12]}]}}

ハンズオンが半音になってしまう

05 S3 への音声ファイルアップロードをトリガに Lambda を起動し Transcribe するパイプラインを作る

IAM修正

コマンド
# AWS管理ポリシー
AWS_MGMT_POLICY_NAME="AmazonTranscribeFullAccess" \
&& echo ${AWS_MGMT_POLICY_NAME}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME} \
    --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}

# AWS管理ポリシー
AWS_MGMT_POLICY_NAME="AmazonS3FullAccess" \
&& echo ${AWS_MGMT_POLICY_NAME}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME} \
    --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-73-220 ~]$ AWS_MGMT_POLICY_NAME="AmazonTranscribeFullAccess" \
> && echo ${AWS_MGMT_POLICY_NAME}
AmazonTranscribeFullAccess
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME} \
>     --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-73-220 ~]$ AWS_MGMT_POLICY_NAME="AmazonS3FullAccess" \
> && echo ${AWS_MGMT_POLICY_NAME}
AmazonS3FullAccess
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME} \
>     --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}

Lambda関数更新

ソースコード更新

コマンド
cat << EOF > lambda_function.py
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='ja-JP',
            Media={
                'MediaFileUri': 'https://s3.ap-northeast-1.amazonaws.com/' + bucket + '/' + key
            },
            OutputBucketName="${S3_BUCKET_NAME_2}"
        )
    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
EOF

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat << EOF > lambda_function.py
> 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='ja-JP',
>             Media={
>                 'MediaFileUri': 'https://s3.ap-northeast-1.amazonaws.com/' + bucket + '/' + key
>             },
>             OutputBucketName="${S3_BUCKET_NAME_2}"
>         )
>     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
> EOF

デプロイパッケージの作成

コマンド
zip function.zip lambda_function.py

出力
[cloudshell-user@ip-10-132-73-220 ~]$ zip function.zip lambda_function.py
updating: lambda_function.py (deflated 46%)

Lambda関数の更新

コマンド
# Lambda関数の更新
aws lambda update-function-code \
    --function-name ${LAMBDA_FUNCTION_NAME}  \
    --zip-file fileb://function.zip

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # Lambda関数の更新
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda update-function-code \
>     --function-name ${LAMBDA_FUNCTION_NAME}  \
>     --zip-file fileb://function.zip
{
    "FunctionName": "transcribe-function",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:transcribe-function",
    "Runtime": "python3.10",
    "Role": "arn:aws:iam::999999999999:role/transcribe-function-role",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 691,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-09-29T08:08:46.000+0000",
    "CodeSha256": "f//PUiA9FQQ+LsS2kgcyUO4tHEsJJlaakfL/lCebukU=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "459b1b9e-eed2-48a9-ab4f-6a2efd3d20a3",
    "State": "Active",
    "LastUpdateStatus": "InProgress",
    "LastUpdateStatusReason": "The function is being created.",
    "LastUpdateStatusReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
    },
    "RuntimeVersionConfig": {
        "RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086"
    },
    "LoggingConfig": {
        "LogFormat": "Text",
        "LogGroup": "/aws/lambda/transcribe-function"
    }
}

S3にファイルをアップロード

コマンド
# アップロードファイル名
UPLOAD_FILENAME="h4b-serverless-3.mp3" \
&& echo ${UPLOAD_FILENAME}

# アップロード
aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ UPLOAD_FILENAME="h4b-serverless-3.mp3" \
> && echo ${UPLOAD_FILENAME}
h4b-serverless-3.mp3
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/
upload: ./h4b-serverless-3.mp3 to s3://h4b-serverless-3-input-20240929/h4b-serverless-3.mp3

トランスクリプションジョブ一覧確認

コマンド
# トランスクリプションジョブ一覧確認
aws transcribe list-transcription-jobs

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # トランスクリプションジョブ一覧確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws transcribe list-transcription-jobs
{
    "TranscriptionJobSummaries": [
        {
            "TranscriptionJobName": "20240929081822_Transcription",
            "CreationTime": "2024-09-29T17:18:22.780000+09:00",
            "StartTime": "2024-09-29T17:18:22.802000+09:00",
            "CompletionTime": "2024-09-29T17:18:35.444000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        },
        {
            "TranscriptionJobName": "Test-Job",
            "CreationTime": "2024-09-29T16:55:31.482000+09:00",
            "StartTime": "2024-09-29T16:55:31.505000+09:00",
            "CompletionTime": "2024-09-29T16:55:42.879000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        }
    ]
}

S3バケット内のオブジェクトを確認

コマンド
# S3バケット内のオブジェクトを確認
aws s3api list-object-versions \
    --bucket ${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケット内のオブジェクトを確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api list-object-versions \
>     --bucket ${S3_BUCKET_NAME_2}
{
    "Versions": [
        {
            "ETag": "\"d751713988987e9331980363e24189ce\"",
            "Size": 2,
            "StorageClass": "STANDARD",
            "Key": ".write_access_check_file.temp",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:18:23+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"1f6856b6b731605a5c910682046378be\"",
            "Size": 2011,
            "StorageClass": "STANDARD",
            "Key": "20240929081822_Transcription.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:18:36+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"40033c4f71ea9b9cc33b3201afd6c613\"",
            "Size": 1991,
            "StorageClass": "STANDARD",
            "Key": "Test-Job.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T07:55:43+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        }
    ],
    "RequestCharged": null
}

S3からファイルをダウンロード

コマンド
# ダウンロードファイル名
DOWNLOAD_FILENAME="20240929081822_Transcription.json" \
&& echo ${DOWNLOAD_FILENAME}

# ダウンロード
aws s3 cp s3://${S3_BUCKET_NAME_2}/${DOWNLOAD_FILENAME} ./

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # ダウンロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ DOWNLOAD_FILENAME="20240929081822_Transcription.json" \
> && echo ${DOWNLOAD_FILENAME}
20240929081822_Transcription.json
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ダウンロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp s3://${S3_BUCKET_NAME_2}/${DOWNLOAD_FILENAME} ./
download: s3://h4b-serverless-3-output-20240929/20240929081822_Transcription.json to ./20240929081822_Transcription.json

ダウンロードしたファイルを確認

コマンド
cat ${DOWNLOAD_FILENAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat ${DOWNLOAD_FILENAME}
{"jobName":"20240929081822_Transcription","accountId":"999999999999","status":"COMPLETED","results":{"transcripts":[{"transcript":"半音順調ですか?手を動かすの楽しいですよ"}],"items":[{"id":0,"type":"pronunciation","alternatives":[{"confidence":"0.996","content":"半"}],"start_time":"0.1","end_time":"0.4"},{"id":1,"type":"pronunciation","alternatives":[{"confidence":"0.611","content":"音"}],"start_time":"0.409","end_time":"0.74"},{"id":2,"type":"pronunciation","alternatives":[{"confidence":"0.997","content":"順調"}],"start_time":"0.75","end_time":"1.179"},{"id":3,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"です"}],"start_time":"1.19","end_time":"1.5"},{"id":4,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"か"}],"start_time":"1.509","end_time":"1.73"},{"id":5,"type":"punctuation","alternatives":[{"confidence":"0.0","content":"?"}]},{"id":6,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"手"}],"start_time":"2.19","end_time":"2.339"},{"id":7,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"を"}],"start_time":"2.349","end_time":"2.5"},{"id":8,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"動かす"}],"start_time":"2.509","end_time":"3.059"},{"id":9,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"の"}],"start_time":"3.069","end_time":"3.21"},{"id":10,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"楽しい"}],"start_time":"3.4","end_time":"3.92"},{"id":11,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"です"}],"start_time":"3.93","end_time":"4.219"},{"id":12,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"よ"}],"start_time":"4.23","end_time":"4.519"}],"audio_segments":[{"id":0,"transcript":"半音順調ですか?手を動かすの楽しいですよ","start_time":"0.0","end_time":"4.63","items":[0,1,2,3,4,5,6,7,8,9,10,11,12]}]}}

ハンズオンが半音になってしまう

06 パイプラインで文字起こししたテキストを Comprehend で感情分析する

Comprehend作成

テスト1

コマンド
ARTICLE="ハンズオン楽しいです!" \
&& echo ${ARTICLE}

aws comprehend detect-sentiment --language-code "ja" --text "${ARTICLE}"

出力
[cloudshell-user@ip-10-132-73-220 ~]$ ARTICLE="ハンズオン楽しいです!" \
> && echo ${ARTICLE}
ハンズオン楽しいです!
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws comprehend detect-sentiment --language-code "ja" --text "${ARTICLE}"
{
    "Sentiment": "POSITIVE",
    "SentimentScore": {
        "Positive": 0.9994205236434937,
        "Negative": 5.861550016561523e-05,
        "Neutral": 0.0005112771177664399,
        "Mixed": 9.625600796425715e-06
    }
}

テスト2

コマンド
ARTICLE="ハンズオン難しいです!" \
&& echo ${ARTICLE}

aws comprehend detect-sentiment --language-code "ja" --text "${ARTICLE}"

出力
[cloudshell-user@ip-10-132-73-220 ~]$ ARTICLE="ハンズオン難しいです!" \
> && echo ${ARTICLE}
ハンズオン難しいです!
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws comprehend detect-sentiment --language-code "ja" --text "${ARTICLE}"
{
    "Sentiment": "NEGATIVE",
    "SentimentScore": {
        "Positive": 0.008654012344777584,
        "Negative": 0.9865438342094421,
        "Neutral": 0.004730266984552145,
        "Mixed": 7.191118493210524e-05
    }
}

Lambda関数作成

変数

コマンド
LAMBDA_FUNCTION_NAME_2="comprehend-function" \
&& echo ${LAMBDA_FUNCTION_NAME_2}

# IAMポリシー名1
IAM_POLICY_NAME_3="AWSLambdaBasicExecutionRole-${LAMBDA_FUNCTION_NAME_2}" \
&& echo ${IAM_POLICY_NAME_3}

# IAMポリシー名2
IAM_POLICY_NAME_4="AWSLambdaS3ExecutionRole-${LAMBDA_FUNCTION_NAME_2}" \
&& echo ${IAM_POLICY_NAME_4}

# IAMロール名
IAM_ROLE_NAME_2="${LAMBDA_FUNCTION_NAME_2}-role" \
&& echo ${IAM_ROLE_NAME_2}

# ランタイム
LAMBDA_RUNTIME="python3.10" \
&& echo ${LAMBDA_RUNTIME}

# アカウントID
ACCOUNT_ID="999999999999" \
&& echo ${ACCOUNT_ID}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ LAMBDA_FUNCTION_NAME_2="comprehend-function" \
> && echo ${LAMBDA_FUNCTION_NAME_2}
comprehend-function
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMポリシー名1
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_NAME_3="AWSLambdaBasicExecutionRole-${LAMBDA_FUNCTION_NAME_2}" \
> && echo ${IAM_POLICY_NAME_3}
AWSLambdaBasicExecutionRole-comprehend-function
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMポリシー名2
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_NAME_4="AWSLambdaS3ExecutionRole-${LAMBDA_FUNCTION_NAME_2}" \
> && echo ${IAM_POLICY_NAME_4}
AWSLambdaS3ExecutionRole-comprehend-function
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロール名
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_ROLE_NAME_2="${LAMBDA_FUNCTION_NAME_2}-role" \
> && echo ${IAM_ROLE_NAME_2}
comprehend-function-role
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ランタイム
[cloudshell-user@ip-10-132-73-220 ~]$ LAMBDA_RUNTIME="python3.10" \
> && echo ${LAMBDA_RUNTIME}
python3.10
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アカウントID
[cloudshell-user@ip-10-132-73-220 ~]$ ACCOUNT_ID="999999999999" \
> && echo ${ACCOUNT_ID}
999999999999

IAMポリシー作成

AWSLambdaBasicExecutionRole

コマンド
# AWSLambdaBasicExecutionRole
# ポリシードキュメントの作成
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:log-group:/aws/lambda/${LAMBDA_FUNCTION_NAME_2}:*"
            ]
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${IAM_POLICY_NAME_3} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
IAM_POLICY_ARN_3=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${IAM_POLICY_NAME_3}'].Arn" \
        --output text
) \
&& echo ${IAM_POLICY_ARN_3}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # AWSLambdaBasicExecutionRole
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシードキュメントの作成
[cloudshell-user@ip-10-132-73-220 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": "logs:CreateLogGroup",
>             "Resource": "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:*"
>         },
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "logs:CreateLogStream",
>                 "logs:PutLogEvents"
>             ],
>             "Resource": [
>                 "arn:aws:logs:ap-northeast-1:${ACCOUNT_ID}:log-group:/aws/lambda/${LAMBDA_FUNCTION_NAME_2}:*"
>             ]
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:ap-northeast-1:999999999999:*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/lambda/comprehend-function:*" ] } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-1:999999999999:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/lambda/comprehend-function:*"
            ]
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam create-policy \
>     --policy-name ${IAM_POLICY_NAME_3} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "AWSLambdaBasicExecutionRole-comprehend-function",
        "PolicyId": "ANPAWFKRCMKOQW5QIFRXV",
        "Arn": "arn:aws:iam::999999999999:policy/AWSLambdaBasicExecutionRole-comprehend-function",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-29T08:31:06+00:00",
        "UpdateDate": "2024-09-29T08:31:06+00:00"
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ARN取得
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_ARN_3=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${IAM_POLICY_NAME_3}'].Arn" \
>         --output text
> ) \
> && echo ${IAM_POLICY_ARN_3}
arn:aws:iam::999999999999:policy/AWSLambdaBasicExecutionRole-comprehend-function

AWSLambdaS3ExecutionRole

コマンド
# AWSLambdaS3ExecutionRole
# ポリシードキュメントの作成
POLICY_DOCUMENT_JSON=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
EOF
) \
&& echo ${POLICY_DOCUMENT_JSON}

# JSONフォーマットの確認
echo ${POLICY_DOCUMENT_JSON} | python -m json.tool

# ポリシーの作成
aws iam create-policy \
    --policy-name ${IAM_POLICY_NAME_4} \
    --policy-document "${POLICY_DOCUMENT_JSON}"

# ARN取得
IAM_POLICY_ARN_4=$(
    aws iam list-policies \
        --query "Policies[?PolicyName=='${IAM_POLICY_NAME_4}'].Arn" \
        --output text
) \
&& echo ${IAM_POLICY_ARN_4}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # AWSLambdaS3ExecutionRole
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシードキュメントの作成
[cloudshell-user@ip-10-132-73-220 ~]$ POLICY_DOCUMENT_JSON=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Action": [
>                 "s3:GetObject"
>             ],
>             "Resource": "arn:aws:s3:::*"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${POLICY_DOCUMENT_JSON}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::*" } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${POLICY_DOCUMENT_JSON} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ポリシーの作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam create-policy \
>     --policy-name ${IAM_POLICY_NAME_4} \
>     --policy-document "${POLICY_DOCUMENT_JSON}"
{
    "Policy": {
        "PolicyName": "AWSLambdaS3ExecutionRole-comprehend-function",
        "PolicyId": "ANPAWFKRCMKOWZ7TFX5RM",
        "Arn": "arn:aws:iam::999999999999:policy/AWSLambdaS3ExecutionRole-comprehend-function",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2024-09-29T08:31:53+00:00",
        "UpdateDate": "2024-09-29T08:31:53+00:00"
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ARN取得
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_POLICY_ARN_4=$(
>     aws iam list-policies \
>         --query "Policies[?PolicyName=='${IAM_POLICY_NAME_4}'].Arn" \
>         --output text
> ) \
> && echo ${IAM_POLICY_ARN_4}
arn:aws:iam::999999999999:policy/AWSLambdaS3ExecutionRole-comprehend-function

IAMロール

コマンド
# 信頼関係ポリシードキュメントの作成
ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF
) \
&& echo ${ASSUME_ROLE_POLICY_DOCUMENT}

# JSONフォーマットの確認
echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool

# IAMロールの作成
aws iam create-role \
    --role-name ${IAM_ROLE_NAME_2} \
    --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"

# ARN取得
IAM_ROLE_ARN_2=$(
    aws iam get-role \
        --role-name ${IAM_ROLE_NAME_2} \
        --query 'Role.Arn' --output text
) \
&& echo ${IAM_ROLE_ARN_2}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME_2} \
    --policy-arn ${IAM_POLICY_ARN_3}

aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME_2} \
    --policy-arn ${IAM_POLICY_ARN_4}

# AWS管理ポリシー
AWS_MGMT_POLICY_NAME="AmazonS3FullAccess" \
&& echo ${AWS_MGMT_POLICY_NAME}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME_2} \
    --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}

# AWS管理ポリシー
AWS_MGMT_POLICY_NAME="ComprehendFullAccess" \
&& echo ${AWS_MGMT_POLICY_NAME}

# IAMロールにポリシーをアタッチ
aws iam attach-role-policy \
    --role-name ${IAM_ROLE_NAME_2} \
    --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 信頼関係ポリシードキュメントの作成
[cloudshell-user@ip-10-132-73-220 ~]$ ASSUME_ROLE_POLICY_DOCUMENT=$(cat << EOF
> {
>     "Version": "2012-10-17",
>     "Statement": [
>         {
>             "Effect": "Allow",
>             "Principal": {
>                 "Service": "lambda.amazonaws.com"
>             },
>             "Action": "sts:AssumeRole"
>         }
>     ]
> }
> EOF
> ) \
> && echo ${ASSUME_ROLE_POLICY_DOCUMENT}
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${ASSUME_ROLE_POLICY_DOCUMENT} | python -m json.tool
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールの作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam create-role \
>     --role-name ${IAM_ROLE_NAME_2} \
>     --assume-role-policy-document "${ASSUME_ROLE_POLICY_DOCUMENT}"
{
    "Role": {
        "Path": "/",
        "RoleName": "comprehend-function-role",
        "RoleId": "AROAWFKRCMKOV5PYZUZWU",
        "Arn": "arn:aws:iam::999999999999:role/comprehend-function-role",
        "CreateDate": "2024-09-29T08:32:38+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ARN取得
[cloudshell-user@ip-10-132-73-220 ~]$ IAM_ROLE_ARN_2=$(
>     aws iam get-role \
>         --role-name ${IAM_ROLE_NAME_2} \
>         --query 'Role.Arn' --output text
> ) \
> && echo ${IAM_ROLE_ARN_2}
arn:aws:iam::999999999999:role/comprehend-function-role
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME_2} \
>     --policy-arn ${IAM_POLICY_ARN_3}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME_2} \
>     --policy-arn ${IAM_POLICY_ARN_4}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-73-220 ~]$ AWS_MGMT_POLICY_NAME="AmazonS3FullAccess" \
> && echo ${AWS_MGMT_POLICY_NAME}
AmazonS3FullAccess
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME_2} \
>     --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # AWS管理ポリシー
[cloudshell-user@ip-10-132-73-220 ~]$ AWS_MGMT_POLICY_NAME="ComprehendFullAccess" \
> && echo ${AWS_MGMT_POLICY_NAME}
ComprehendFullAccess
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールにポリシーをアタッチ
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam attach-role-policy \
>     --role-name ${IAM_ROLE_NAME_2} \
>     --policy-arn arn:aws:iam::aws:policy/${AWS_MGMT_POLICY_NAME}

Lambdaソースコード

コマンド
cat << EOF > lambda_function.py
import json
import urllib.parse
import boto3

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

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:
        response = s3.get_object(Bucket=bucket, Key=key)

        body = json.load(response['Body'])
        transcript = body['results']['transcripts'][0]['transcript']

        sentiment_response = comprehend.detect_sentiment(
            Text=transcript,
            LanguageCode='ja'
        )

        sentiment_score = sentiment_response.get('SentimentScore')
        print(sentiment_score)
    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
EOF

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat << EOF > lambda_function.py
> import json
> import urllib.parse
> import boto3
> 
> s3 = boto3.client('s3')
> comprehend = boto3.client('comprehend')
> 
> 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:
>         response = s3.get_object(Bucket=bucket, Key=key)
> 
>         body = json.load(response['Body'])
>         transcript = body['results']['transcripts'][0]['transcript']
> 
>         sentiment_response = comprehend.detect_sentiment(
>             Text=transcript,
>             LanguageCode='ja'
>         )
> 
>         sentiment_score = sentiment_response.get('SentimentScore')
>         print(sentiment_score)
>     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
> EOF

デプロイパッケージの作成

コマンド
zip function.zip lambda_function.py

出力
[cloudshell-user@ip-10-132-73-220 ~]$ zip function.zip lambda_function.py
updating: lambda_function.py (deflated 51%)

Lambda関数の作成

コマンド
# Lambda関数の作成
aws lambda create-function \
    --function-name ${LAMBDA_FUNCTION_NAME_2} \
    --role ${IAM_ROLE_ARN_2} \
    --zip-file fileb://function.zip \
    --runtime ${LAMBDA_RUNTIME} \
    --handler lambda_function.lambda_handler \

# ARNの取得
LAMBDA_FUNCTION_ARN_2=$(
    aws lambda list-functions \
        --query "Functions[?FunctionName=='${LAMBDA_FUNCTION_NAME_2}'].FunctionArn" \
        --output text
) \
&& echo ${LAMBDA_FUNCTION_ARN_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # Lambda関数の作成
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda create-function \
>     --function-name ${LAMBDA_FUNCTION_NAME_2} \
>     --role ${IAM_ROLE_ARN_2} \
>     --zip-file fileb://function.zip \
>     --runtime ${LAMBDA_RUNTIME} \
>     --handler lambda_function.lambda_handler \
> 
{
    "FunctionName": "comprehend-function",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:comprehend-function",
    "Runtime": "python3.10",
    "Role": "arn:aws:iam::999999999999:role/comprehend-function-role",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 638,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-09-29T08:34:29.004+0000",
    "CodeSha256": "CudSXtQVY769LoeB/6hrAdUE2J3QTb+3er3ZvuTe4Wk=",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "3a24f919-ad39-4b1b-9f22-863df931adba",
    "State": "Pending",
    "StateReason": "The function is being created.",
    "StateReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
    },
    "RuntimeVersionConfig": {
        "RuntimeVersionArn": "arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086"
    },
    "LoggingConfig": {
        "LogFormat": "Text",
        "LogGroup": "/aws/lambda/comprehend-function"
    }
}
[cloudshell-user@ip-10-132-73-220 ~]$ # ARNの取得
[cloudshell-user@ip-10-132-73-220 ~]$ LAMBDA_FUNCTION_ARN_2=$(
>     aws lambda list-functions \
>         --query "Functions[?FunctionName=='${LAMBDA_FUNCTION_NAME_2}'].FunctionArn" \
>         --output text
> ) \
> && echo ${LAMBDA_FUNCTION_ARN_2}
arn:aws:lambda:ap-northeast-1:999999999999:function:comprehend-function

リソースベースのポリシーステートメント追加

コマンド
# リソースベースのポリシーステートメント追加
aws lambda add-permission \
    --function-name ${LAMBDA_FUNCTION_NAME_2} \
    --principal s3.amazonaws.com \
    --statement-id S3InvokePermission \
    --action "lambda:InvokeFunction" \
    --source-arn arn:aws:s3:::${S3_BUCKET_NAME_2} \
    --source-account ${ACCOUNT_ID}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # リソースベースのポリシーステートメント追加
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda add-permission \
>     --function-name ${LAMBDA_FUNCTION_NAME_2} \
>     --principal s3.amazonaws.com \
>     --statement-id S3InvokePermission \
>     --action "lambda:InvokeFunction" \
>     --source-arn arn:aws:s3:::${S3_BUCKET_NAME_2} \
>     --source-account ${ACCOUNT_ID}
{
    "Statement": "{\"Sid\":\"S3InvokePermission\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:999999999999:function:comprehend-function\",\"Condition\":{\"StringEquals\":{\"AWS:SourceAccount\":\"999999999999\"},\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::h4b-serverless-3-output-20240929\"}}}"
}

イベント通知設定用JSON

コマンド
# イベント通知設定用JSON
S3_NOTIFICATION_CONFIGURATION=$(cat << EOF
{
    "LambdaFunctionConfigurations": [
        {
            "LambdaFunctionArn": "${LAMBDA_FUNCTION_ARN_2}",
            "Events": ["s3:ObjectCreated:*"],
            "Filter": {
                "Key": {
                    "FilterRules": [
                        {
                            "Name": "Suffix",
                            "Value": ".json"
                        }
                    ]
                }
            }
        }
    ]
}
EOF
) \
&& echo ${S3_NOTIFICATION_CONFIGURATION}

# JSONフォーマットの確認
echo ${S3_NOTIFICATION_CONFIGURATION} | python -m json.tool

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # イベント通知設定用JSON
[cloudshell-user@ip-10-132-73-220 ~]$ S3_NOTIFICATION_CONFIGURATION=$(cat << EOF
> {
>     "LambdaFunctionConfigurations": [
>         {
>             "LambdaFunctionArn": "${LAMBDA_FUNCTION_ARN_2}",
>             "Events": ["s3:ObjectCreated:*"],
>             "Filter": {
>                 "Key": {
>                     "FilterRules": [
>                         {
>                             "Name": "Suffix",
>                             "Value": ".json"
>                         }
>                     ]
>                 }
>             }
>         }
>     ]
> }
> EOF
> ) \
> && echo ${S3_NOTIFICATION_CONFIGURATION}
{ "LambdaFunctionConfigurations": [ { "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:comprehend-function", "Events": ["s3:ObjectCreated:*"], "Filter": { "Key": { "FilterRules": [ { "Name": "Suffix", "Value": ".json" } ] } } } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${S3_NOTIFICATION_CONFIGURATION} | python -m json.tool
{
    "LambdaFunctionConfigurations": [
        {
            "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:comprehend-function",
            "Events": [
                "s3:ObjectCreated:*"
            ],
            "Filter": {
                "Key": {
                    "FilterRules": [
                        {
                            "Name": "Suffix",
                            "Value": ".json"
                        }
                    ]
                }
            }
        }
    ]
}

S3 バケットにイベント通知を設定して Lambda をトリガー

コマンド
aws s3api put-bucket-notification-configuration \
    --bucket ${S3_BUCKET_NAME_2} \
    --notification-configuration "${S3_NOTIFICATION_CONFIGURATION}"

出力
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api put-bucket-notification-configuration \
>     --bucket ${S3_BUCKET_NAME_2} \
>     --notification-configuration "${S3_NOTIFICATION_CONFIGURATION}"

S3にファイルをアップロード

コマンド
# アップロードファイル名
UPLOAD_FILENAME="h4b-serverless-3.mp3" \
&& echo ${UPLOAD_FILENAME}

# アップロード
aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ UPLOAD_FILENAME="h4b-serverless-3.mp3" \
> && echo ${UPLOAD_FILENAME}
h4b-serverless-3.mp3
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/
upload: ./h4b-serverless-3.mp3 to s3://h4b-serverless-3-input-20240929/h4b-serverless-3.mp3

トランスクリプションジョブ一覧確認

コマンド
# トランスクリプションジョブ一覧確認
aws transcribe list-transcription-jobs

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # トランスクリプションジョブ一覧確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws transcribe list-transcription-jobs
{
    "TranscriptionJobSummaries": [
        {
            "TranscriptionJobName": "20240929083905_Transcription",
            "CreationTime": "2024-09-29T17:39:06.165000+09:00",
            "StartTime": "2024-09-29T17:39:06.191000+09:00",
            "CompletionTime": "2024-09-29T17:39:13.852000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        },
        {
            "TranscriptionJobName": "20240929081822_Transcription",
            "CreationTime": "2024-09-29T17:18:22.780000+09:00",
            "StartTime": "2024-09-29T17:18:22.802000+09:00",
            "CompletionTime": "2024-09-29T17:18:35.444000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        },
        {
            "TranscriptionJobName": "Test-Job",
            "CreationTime": "2024-09-29T16:55:31.482000+09:00",
            "StartTime": "2024-09-29T16:55:31.505000+09:00",
            "CompletionTime": "2024-09-29T16:55:42.879000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        }
    ]
}

S3バケット内のオブジェクトを確認

コマンド
# S3バケット内のオブジェクトを確認
aws s3api list-object-versions \
    --bucket ${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケット内のオブジェクトを確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api list-object-versions \
>     --bucket ${S3_BUCKET_NAME_2}
{
    "Versions": [
        {
            "ETag": "\"d751713988987e9331980363e24189ce\"",
            "Size": 2,
            "StorageClass": "STANDARD",
            "Key": ".write_access_check_file.temp",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:39:07+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"1f6856b6b731605a5c910682046378be\"",
            "Size": 2011,
            "StorageClass": "STANDARD",
            "Key": "20240929081822_Transcription.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:18:36+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"c594426cf1af4afee49d6890daad09de\"",
            "Size": 2011,
            "StorageClass": "STANDARD",
            "Key": "20240929083905_Transcription.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:39:14+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"40033c4f71ea9b9cc33b3201afd6c613\"",
            "Size": 1991,
            "StorageClass": "STANDARD",
            "Key": "Test-Job.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T07:55:43+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        }
    ],
    "RequestCharged": null
}

CloudWatchロググループ確認

コマンド
# 最新のログストリームを取得
LATEST_LOG_STREAM=$(
    aws logs describe-log-streams \
        --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
        --order-by LastEventTime \
        --descending \
        --limit 1 \
        --query 'logStreams[0].logStreamName' \
        --output text
) \
&& echo ${LATEST_LOG_STREAM}

# ログの確認
aws logs get-log-events \
    --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
    --log-stream-name ${LATEST_LOG_STREAM} \
    --no-cli-pager

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 最新のログストリームを取得
[cloudshell-user@ip-10-132-73-220 ~]$ LATEST_LOG_STREAM=$(
>     aws logs describe-log-streams \
>         --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
>         --order-by LastEventTime \
>         --descending \
>         --limit 1 \
>         --query 'logStreams[0].logStreamName' \
>         --output text
> ) \
> && echo ${LATEST_LOG_STREAM}
2024/09/29/[$LATEST]a225bbabb4ce4e5b9aba78d06a1d30a0
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ログの確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws logs get-log-events \
>     --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
>     --log-stream-name ${LATEST_LOG_STREAM} \
>     --no-cli-pager
{
    "events": [
        {
            "timestamp": 1727599154655,
            "message": "INIT_START Runtime Version: python:3.10.v38\tRuntime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086\n",
            "ingestionTime": 1727599155543
        },
        {
            "timestamp": 1727599155089,
            "message": "START RequestId: b2a46ec3-34ba-43d1-91eb-8aecaad12218 Version: $LATEST\n",
            "ingestionTime": 1727599155543
        },
        {
            "timestamp": 1727599155978,
            "message": "{'Positive': 0.9275622963905334, 'Negative': 0.0006652617012150586, 'Neutral': 0.07174542546272278, 'Mixed': 2.7032214347855188e-05}\n",
            "ingestionTime": 1727599165029
        },
        {
            "timestamp": 1727599155992,
            "message": "END RequestId: b2a46ec3-34ba-43d1-91eb-8aecaad12218\n",
            "ingestionTime": 1727599165029
        },
        {
            "timestamp": 1727599155992,
            "message": "REPORT RequestId: b2a46ec3-34ba-43d1-91eb-8aecaad12218\tDuration: 902.98 ms\tBilled Duration: 903 ms\tMemory Size: 128 MB\tMax Memory Used: 81 MB\tInit Duration: 433.03 ms\t\n",
            "ingestionTime": 1727599165029
        }
    ],
    "nextForwardToken": "f/38526748582974151019971469683097397755737395250988187650/s",
    "nextBackwardToken": "b/38526748553158054689536026531396345019833403355502411776/s"
}

07 [Option] Amazon Polly で作成した音声ファイルをパイプラインに投入する

SSMLテスト

コマンド
ARTICLE='<speak>こんにちは、金澤です。<amazon:effect name="whispered">囁いたり、</amazon:effect><prosody volume="x-loud">声の大きさを変えたりできますよ !</prosody></speak>' \
&& echo ${ARTICLE}

aws polly synthesize-speech \
    --output-format mp3 \
    --text-type ssml \
    --text "${ARTICLE}" \
    --voice-id Takumi \
    output.mp3

出力
[cloudshell-user@ip-10-132-73-220 ~]$ ARTICLE='<speak>こんにちは、金澤です。<amazon:effect name="whispered">囁いたり、</amazon:effect><prosody volume="x-loud">声の大きさを変えたりできますよ !</prosody></speak>' \
> && echo ${ARTICLE}
<speak>こんにちは、金澤です。<amazon:effect name="whispered">囁いたり、</amazon:effect><prosody volume="x-loud">声の大きさを変えたりでき ますよ !</prosody></speak>
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws polly synthesize-speech \
>     --output-format mp3 \
>     --text-type ssml \
>     --text "${ARTICLE}" \
>     --voice-id Takumi \
>     output.mp3
{
    "ContentType": "audio/mpeg",
    "RequestCharacters": "35"
}

プレーンテキストテスト

コマンド
ARTICLE="ハンズオン動画を作るのも楽しいですよ" \
&& echo ${ARTICLE}

aws polly synthesize-speech \
    --output-format mp3 \
    --text "${ARTICLE}" \
    --voice-id Takumi \
    output.mp3

出力
[cloudshell-user@ip-10-132-73-220 ~]$ ARTICLE="ハンズオン動画を作るのも楽しいですよ" \
> && echo ${ARTICLE}
ハンズオン動画を作るのも楽しいですよ
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws polly synthesize-speech \
>     --output-format mp3 \
>     --text "${ARTICLE}" \
>     --voice-id Takumi \
>     output.mp3
{
    "ContentType": "audio/mpeg",
    "RequestCharacters": "18"
}

S3にファイルをアップロード

コマンド
# アップロードファイル名
UPLOAD_FILENAME="output.mp3" \
&& echo ${UPLOAD_FILENAME}

# アップロード
aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ UPLOAD_FILENAME="output.mp3" \
> && echo ${UPLOAD_FILENAME}
output.mp3
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # アップロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp ${UPLOAD_FILENAME} s3://${S3_BUCKET_NAME}/
upload: ./output.mp3 to s3://h4b-serverless-3-input-20240929/output.mp3

トランスクリプションジョブ一覧確認

コマンド
# トランスクリプションジョブ一覧確認
aws transcribe list-transcription-jobs

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # トランスクリプションジョブ一覧確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws transcribe list-transcription-jobs
{
    "TranscriptionJobSummaries": [
        {
            "TranscriptionJobName": "20240929085301_Transcription",
            "CreationTime": "2024-09-29T17:53:01.861000+09:00",
            "StartTime": "2024-09-29T17:53:01.889000+09:00",
            "CompletionTime": "2024-09-29T17:53:09.548000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        },
        {
            "TranscriptionJobName": "20240929083905_Transcription",
            "CreationTime": "2024-09-29T17:39:06.165000+09:00",
            "StartTime": "2024-09-29T17:39:06.191000+09:00",
            "CompletionTime": "2024-09-29T17:39:13.852000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        },
        {
            "TranscriptionJobName": "20240929081822_Transcription",
            "CreationTime": "2024-09-29T17:18:22.780000+09:00",
            "StartTime": "2024-09-29T17:18:22.802000+09:00",
            "CompletionTime": "2024-09-29T17:18:35.444000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        },
        {
            "TranscriptionJobName": "Test-Job",
            "CreationTime": "2024-09-29T16:55:31.482000+09:00",
            "StartTime": "2024-09-29T16:55:31.505000+09:00",
            "CompletionTime": "2024-09-29T16:55:42.879000+09:00",
            "LanguageCode": "ja-JP",
            "TranscriptionJobStatus": "COMPLETED",
            "OutputLocationType": "CUSTOMER_BUCKET"
        }
    ]
}

S3バケット内のオブジェクトを確認

コマンド
# S3バケット内のオブジェクトを確認
aws s3api list-object-versions \
    --bucket ${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケット内のオブジェクトを確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api list-object-versions \
>     --bucket ${S3_BUCKET_NAME_2}
{
    "Versions": [
        {
            "ETag": "\"d751713988987e9331980363e24189ce\"",
            "Size": 2,
            "StorageClass": "STANDARD",
            "Key": ".write_access_check_file.temp",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:53:02+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"1f6856b6b731605a5c910682046378be\"",
            "Size": 2011,
            "StorageClass": "STANDARD",
            "Key": "20240929081822_Transcription.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:18:36+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"c594426cf1af4afee49d6890daad09de\"",
            "Size": 2011,
            "StorageClass": "STANDARD",
            "Key": "20240929083905_Transcription.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:39:14+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"0bc67d6f1d0fbacccddf3b62bd667dd4\"",
            "Size": 1467,
            "StorageClass": "STANDARD",
            "Key": "20240929085301_Transcription.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T08:53:10+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        },
        {
            "ETag": "\"40033c4f71ea9b9cc33b3201afd6c613\"",
            "Size": 1991,
            "StorageClass": "STANDARD",
            "Key": "Test-Job.json",
            "VersionId": "null",
            "IsLatest": true,
            "LastModified": "2024-09-29T07:55:43+00:00",
            "Owner": {
                "DisplayName": "hironobu5500+parent1",
                "ID": "974cd83317461904fcbad632a42045ad8cd85cb24065c65f2ca62b7e35d84078"
            }
        }
    ],
    "RequestCharged": null
}

S3からファイルをダウンロード

コマンド
# ダウンロードファイル名
DOWNLOAD_FILENAME="20240929085301_Transcription.json" \
&& echo ${DOWNLOAD_FILENAME}

# ダウンロード
aws s3 cp s3://${S3_BUCKET_NAME_2}/${DOWNLOAD_FILENAME} ./

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # ダウンロードファイル名
[cloudshell-user@ip-10-132-73-220 ~]$ DOWNLOAD_FILENAME="20240929085301_Transcription.json" \
> && echo ${DOWNLOAD_FILENAME}
20240929085301_Transcription.json
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ダウンロード
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3 cp s3://${S3_BUCKET_NAME_2}/${DOWNLOAD_FILENAME} ./
download: s3://h4b-serverless-3-output-20240929/20240929085301_Transcription.json to ./20240929085301_Transcription.json

ダウンロードしたファイルを確認

コマンド
cat ${DOWNLOAD_FILENAME}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ cat ${DOWNLOAD_FILENAME}
{"jobName":"20240929085301_Transcription","accountId":"999999999999","status":"COMPLETED","results":{"transcripts":[{"transcript":"半蔵動画を作るのも楽しいです。"}],"items":[{"id":0,"type":"pronunciation","alternatives":[{"confidence":"0.475","content":"半蔵"}],"start_time":"0.07","end_time":"0.68"},{"id":1,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"動画"}],"start_time":"0.689","end_time":"1.019"},{"id":2,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"を"}],"start_time":"1.029","end_time":"1.139"},{"id":3,"type":"pronunciation","alternatives":[{"confidence":"0.98","content":"作る"}],"start_time":"1.149","end_time":"1.539"},{"id":4,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"の"}],"start_time":"1.549","end_time":"1.779"},{"id":5,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"も"}],"start_time":"1.789","end_time":"1.85"},{"id":6,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"楽しい"}],"start_time":"2.109","end_time":"2.579"},{"id":7,"type":"pronunciation","alternatives":[{"confidence":"0.999","content":"です"}],"start_time":"2.589","end_time":"2.91"},{"id":8,"type":"punctuation","alternatives":[{"confidence":"0.0","content":"。"}]}],"audio_segments":[{"id":0,"transcript":"半蔵動画を作るのも楽しいです。","start_time":"0.0","end_time":"3.059","items":[0,1,2,3,4,5,6,7,8]}]}}

ハンズオンが半蔵になってしまう

CloudWatchロググループ確認

コマンド
# 最新のログストリームを取得
LATEST_LOG_STREAM=$(
    aws logs describe-log-streams \
        --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
        --order-by LastEventTime \
        --descending \
        --limit 1 \
        --query 'logStreams[0].logStreamName' \
        --output text
) \
&& echo ${LATEST_LOG_STREAM}

# ログの確認
aws logs get-log-events \
    --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
    --log-stream-name ${LATEST_LOG_STREAM} \
    --no-cli-pager

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # 最新のログストリームを取得
[cloudshell-user@ip-10-132-73-220 ~]$ LATEST_LOG_STREAM=$(
>     aws logs describe-log-streams \
>         --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
>         --order-by LastEventTime \
>         --descending \
>         --limit 1 \
>         --query 'logStreams[0].logStreamName' \
>         --output text
> ) \
> && echo ${LATEST_LOG_STREAM}
2024/09/29/[$LATEST]e0253d0b21344bc79dd0969b810a4d44
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # ログの確認
[cloudshell-user@ip-10-132-73-220 ~]$ aws logs get-log-events \
>     --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2} \
>     --log-stream-name ${LATEST_LOG_STREAM} \
>     --no-cli-pager
{
    "events": [
        {
            "timestamp": 1727599991164,
            "message": "INIT_START Runtime Version: python:3.10.v38\tRuntime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:cd5b19747c6f456b465655915abd7ec32c616f52b3421c0b532d90cf258e0086\n",
            "ingestionTime": 1727599991827
        },
        {
            "timestamp": 1727599991636,
            "message": "START RequestId: aa5a6975-2846-4378-a020-f442159eed05 Version: $LATEST\n",
            "ingestionTime": 1727599991827
        },
        {
            "timestamp": 1727599992522,
            "message": "{'Positive': 0.9988161325454712, 'Negative': 0.0001258893171325326, 'Neutral': 0.0010536931222304702, 'Mixed': 4.337752670835471e-06}\n",
            "ingestionTime": 1727600001541
        },
        {
            "timestamp": 1727599992531,
            "message": "END RequestId: aa5a6975-2846-4378-a020-f442159eed05\n",
            "ingestionTime": 1727600001541
        },
        {
            "timestamp": 1727599992531,
            "message": "REPORT RequestId: aa5a6975-2846-4378-a020-f442159eed05\tDuration: 895.57 ms\tBilled Duration: 896 ms\tMemory Size: 128 MB\tMax Memory Used: 81 MB\tInit Duration: 469.98 ms\t\n",
            "ingestionTime": 1727600001541
        }
    ],
    "nextForwardToken": "f/38526767238417238653580422891526470985557072310587162626/s",
    "nextBackwardToken": "b/38526767207932119967189061045303899093522372925797826560/s"
}

08 クリーンアップ、まとめ + Next Challenge のススメ

S3削除

コマンド
# オブジェクト一覧取得
OBJECT_LIST=$(
    aws s3api list-object-versions \
        --bucket ${S3_BUCKET_NAME} \
        --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
) \
&& echo ${OBJECT_LIST}

# JSONフォーマットの確認
echo ${OBJECT_LIST} | python -m json.tool

# バケットを空にする
aws s3api delete-objects \
    --bucket ${S3_BUCKET_NAME} \
    --delete "${OBJECT_LIST}"

# S3バケットを削除
aws s3api delete-bucket \
    --bucket ${S3_BUCKET_NAME}


# オブジェクト一覧取得
OBJECT_LIST=$(
    aws s3api list-object-versions \
        --bucket ${S3_BUCKET_NAME_2} \
        --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
) \
&& echo ${OBJECT_LIST}

# JSONフォーマットの確認
echo ${OBJECT_LIST} | python -m json.tool

# バケットを空にする
aws s3api delete-objects \
    --bucket ${S3_BUCKET_NAME_2} \
    --delete "${OBJECT_LIST}"

# S3バケットを削除
aws s3api delete-bucket \
    --bucket ${S3_BUCKET_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # オブジェクト一覧取得
[cloudshell-user@ip-10-132-73-220 ~]$ OBJECT_LIST=$(
>     aws s3api list-object-versions \
>         --bucket ${S3_BUCKET_NAME} \
>         --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
> ) \
> && echo ${OBJECT_LIST}
{ "Objects": [ { "Key": "h4b-serverless-3.mp3", "VersionId": "null" }, { "Key": "output.mp3", "VersionId": "null" } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${OBJECT_LIST} | python -m json.tool
{
    "Objects": [
        {
            "Key": "h4b-serverless-3.mp3",
            "VersionId": "null"
        },
        {
            "Key": "output.mp3",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # バケットを空にする
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api delete-objects \
>     --bucket ${S3_BUCKET_NAME} \
>     --delete "${OBJECT_LIST}"
{
    "Deleted": [
        {
            "Key": "h4b-serverless-3.mp3",
            "VersionId": "null"
        },
        {
            "Key": "output.mp3",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケットを削除
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api delete-bucket \
>     --bucket ${S3_BUCKET_NAME}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # オブジェクト一覧取得
[cloudshell-user@ip-10-132-73-220 ~]$ OBJECT_LIST=$(
>     aws s3api list-object-versions \
>         --bucket ${S3_BUCKET_NAME_2} \
>         --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}'
> ) \
> && echo ${OBJECT_LIST}
{ "Objects": [ { "Key": ".write_access_check_file.temp", "VersionId": "null" }, { "Key": "20240929081822_Transcription.json", "VersionId": "null" }, { "Key": "20240929083905_Transcription.json", "VersionId": "null" }, { "Key": "20240929085301_Transcription.json", "VersionId": "null" }, { "Key": "Test-Job.json", "VersionId": "null" } ] }
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # JSONフォーマットの確認
[cloudshell-user@ip-10-132-73-220 ~]$ echo ${OBJECT_LIST} | python -m json.tool
{
    "Objects": [
        {
            "Key": ".write_access_check_file.temp",
            "VersionId": "null"
        },
        {
            "Key": "20240929081822_Transcription.json",
            "VersionId": "null"
        },
        {
            "Key": "20240929083905_Transcription.json",
            "VersionId": "null"
        },
        {
            "Key": "20240929085301_Transcription.json",
            "VersionId": "null"
        },
        {
            "Key": "Test-Job.json",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # バケットを空にする
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api delete-objects \
>     --bucket ${S3_BUCKET_NAME_2} \
>     --delete "${OBJECT_LIST}"
{
    "Deleted": [
        {
            "Key": "20240929083905_Transcription.json",
            "VersionId": "null"
        },
        {
            "Key": "Test-Job.json",
            "VersionId": "null"
        },
        {
            "Key": "20240929081822_Transcription.json",
            "VersionId": "null"
        },
        {
            "Key": "20240929085301_Transcription.json",
            "VersionId": "null"
        },
        {
            "Key": ".write_access_check_file.temp",
            "VersionId": "null"
        }
    ]
}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # S3バケットを削除
[cloudshell-user@ip-10-132-73-220 ~]$ aws s3api delete-bucket \
>     --bucket ${S3_BUCKET_NAME_2}

IAM削除

WSLambdaBasicExecutionRole

コマンド
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${IAM_ROLE_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${IAM_ROLE_NAME} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${IAM_ROLE_NAME}

# IAMポリシーの削除
aws iam delete-policy \
    --policy-arn ${IAM_POLICY_ARN_1}

aws iam delete-policy \
    --policy-arn ${IAM_POLICY_ARN_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-73-220 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${IAM_ROLE_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::999999999999:policy/AWSLambdaS3ExecutionRole-transcribe-function arn:aws:iam::999999999999:policy/AWSLambdaBasicExecutionRole-transcribe-function arn:aws:iam::aws:policy/AmazonTranscribeFullAccess arn:aws:iam::aws:policy/AmazonS3FullAccess
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-73-220 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${IAM_ROLE_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam delete-role \
>     --role-name ${IAM_ROLE_NAME}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMポリシーの削除
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam delete-policy \
>     --policy-arn ${IAM_POLICY_ARN_1}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam delete-policy \
>     --policy-arn ${IAM_POLICY_ARN_2}

AWSLambdaS3ExecutionRole

コマンド
# ロールにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-role-policies \
        --role-name ${IAM_ROLE_NAME_2} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-role-policy \
        --role-name ${IAM_ROLE_NAME_2} \
        --policy-arn ${POLICY}
done

# IAMロールの削除
aws iam delete-role \
    --role-name ${IAM_ROLE_NAME_2}

# IAMポリシーの削除
aws iam delete-policy \
    --policy-arn ${IAM_POLICY_ARN_3}

aws iam delete-policy \
    --policy-arn ${IAM_POLICY_ARN_4}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # ロールにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-73-220 ~]$ POLICIES=$(
>     aws iam list-attached-role-policies \
>         --role-name ${IAM_ROLE_NAME_2} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::999999999999:policy/AWSLambdaBasicExecutionRole-comprehend-function arn:aws:iam::999999999999:policy/AWSLambdaS3ExecutionRole-comprehend-function arn:aws:iam::aws:policy/ComprehendFullAccess arn:aws:iam::aws:policy/AmazonS3FullAccess
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-73-220 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-role-policy \
>         --role-name ${IAM_ROLE_NAME_2} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMロールの削除
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam delete-role \
>     --role-name ${IAM_ROLE_NAME_2}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ # IAMポリシーの削除
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam delete-policy \
>     --policy-arn ${IAM_POLICY_ARN_3}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws iam delete-policy \
>     --policy-arn ${IAM_POLICY_ARN_4}

ロググループの削除

コマンド
aws logs delete-log-group \
    --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME}

aws logs delete-log-group \
    --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2}
出力
[cloudshell-user@ip-10-132-73-220 ~]$ aws logs delete-log-group \
>     --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws logs delete-log-group \
>     --log-group-name /aws/lambda/${LAMBDA_FUNCTION_NAME_2}

トランスクリプションジョブ削除

コマンド
# すべてのジョブ名を取得し、削除するスクリプト
for job_name in $(aws transcribe list-transcription-jobs --query 'TranscriptionJobSummaries[*].TranscriptionJobName' --output text); do
    echo "Deleting transcription job: $job_name"
    aws transcribe delete-transcription-job --transcription-job-name "${job_name}"
done

出力
[cloudshell-user@ip-10-132-73-220 ~]$ # すべてのジョブ名を取得し、削除するスクリプト
[cloudshell-user@ip-10-132-73-220 ~]$ for job_name in $(aws transcribe list-transcription-jobs --query 'TranscriptionJobSummaries[*].TranscriptionJobName' --output text); do
>     echo "Deleting transcription job: $job_name"
>     aws transcribe delete-transcription-job --transcription-job-name "${job_name}"
> done
Deleting transcription job: 20240929085301_Transcription
Deleting transcription job: 20240929083905_Transcription
Deleting transcription job: 20240929081822_Transcription
Deleting transcription job: Test-Job

Lambda削除

コマンド
aws lambda delete-function \
    --function-name ${LAMBDA_FUNCTION_NAME}

aws lambda delete-function \
    --function-name ${LAMBDA_FUNCTION_NAME_2}

出力
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda delete-function \
>     --function-name ${LAMBDA_FUNCTION_NAME}
[cloudshell-user@ip-10-132-73-220 ~]$ 
[cloudshell-user@ip-10-132-73-220 ~]$ aws lambda delete-function \
>     --function-name ${LAMBDA_FUNCTION_NAME_2}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0