2020-05-03(日)
JAWS-UG 初心者支部&千葉支部 #26 新人さん歓迎!ハンズオン<(オンライン) を CLI でやってみる (ハンズオン 1 編) #jawsug_bgnr
在宅勤務ベースになってオンラインのイベントに参加しやすくなっているので色々手を出している。
先日は JAWS-UG 初心者支部&千葉支部 #26 新人さん歓迎!ハンズオン<(オンライン) に参加して、へーとかほーとか思いながら Lambda やら API Gateway やらを触った (Translate と Transcribe はサービスそのものを初めて知った)。
当日は資料通りにマネジメントコンソールから操作していたが、復習の意味も込めて CLI 経由で改めてやってみる。
ロール作成
とりあえずフル権限で作成。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
$ aws iam create-role \
--role-name translate-function-role \
--assume-role-policy-document file://translate-function-role.json
{
"Role": {
"Path": "/",
"RoleName": "translate-function-role",
"RoleId": "AROA3B7TBQZDJUTAZJSOD",
"Arn": "arn:aws:iam::760182048326:role/translate-function-role",
"CreateDate": "2020-05-03T07:39:02+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}
ロールが何のためのものかは #AWS Lambda の実行ロールを作成する ( SQSの実行権限を与える例 ) の内容がしっくりきた。
AWS Lambda 「が」AWSの他のサービス「を」使うときの許可、ポリシーみたいだ。
Lambda Function を作成
今回はサンプルコードを clone してそのまま使用した。
$ zip translate-function.zip translate-function.py
adding: translate-function.py (deflated 42%)
$ aws lambda create-function \
--function-name translate-function \
--runtime python3.8 \
--role "arn:aws:iam::760182048326:role/translate-function-role" \
--handler translate-function.lambda_handler \
--zip-file fileb://translate-function.zip
{
"FunctionName": "translate-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function",
"Runtime": "python3.8",
"Role": "arn:aws:iam::760182048326:role/translate-function-role",
"Handler": "translate-function.lambda_handler",
"CodeSize": 454,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2020-05-03T08:01:57.762+0000",
"CodeSha256": "undpq1zH+AaJrMaEzHNUAws+D0+g5+6puU/1ieb62kQ=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "17bfdf82-b17c-4a62-b70d-85a71d735432",
"State": "Active",
"LastUpdateStatus": "Successful"
}
実行してみると、
$ aws lambda invoke --function-name translate-function outfile.json
{
"StatusCode": 200,
"FunctionError": "Unhandled",
"ExecutedVersion": "$LATEST"
}
FunctionError
らしい。
{
"errorMessage": "An error occurred (AccessDeniedException) when calling the TranslateText operation: User: arn:aws:sts::760182048326:assumed-role/translate-function-role/translate-function is not authorized to perform: translate:TranslateText",
"errorType": "ClientError",
"stackTrace": [
" File \"/var/task/translate-function.py\", line 9, in lambda_handler\n response = translate.translate_text(\n",
" File \"/var/runtime/botocore/client.py\", line 316, in _api_call\n return self._make_api_call(operation_name, kwargs)\n",
" File \"/var/runtime/botocore/client.py\", line 626, in _make_api_call\n raise error_class(parsed_response, operation_name)\n"
]
}
Amazon Translate のポリシーをアタッチするのを忘れていた。
仕切り直し
TranslateFullAccess をアタッチ。
$ aws iam attach-role-policy \
--role-name translate-function-role \
--policy-arn "arn:aws:iam::aws:policy/TranslateFullAccess"
$ aws iam get-role --role-name translate-function-role
{
"Role": {
"Path": "/",
"RoleName": "translate-function-role",
"RoleId": "AROA3B7TBQZDJUTAZJSOD",
"Arn": "arn:aws:iam::760182048326:role/translate-function-role",
"CreateDate": "2020-05-03T07:39:02+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"MaxSessionDuration": 3600,
"RoleLastUsed": {
"LastUsedDate": "2020-05-03T08:06:35+00:00",
"Region": "ap-northeast-1"
}
}
}
Lambda Function を改めて実行。
$ aws lambda invoke --function-name translate-function outfile.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
今度は成功した。
{
"statusCode": 200,
"body": "{\"output_text\": \"Are you well?\"}"
}
参考
2020-05-04(月)
JAWS-UG 初心者支部&千葉支部 #26 新人さん歓迎!ハンズオン<(オンライン) を CLI でやってみる (ハンズオン 2 編) #jawsug_bgnr
ハンズオン 1 編の続き。
Lambda Function 作成
ロールはハンズオン 1 のときのものを流用する。
$ zip translate-function-with-apigw.zip translate-function-with-apigw.py
adding: translate-function-with-apigw.py (deflated 48%)
$ aws lambda create-function \
--function-name translate-function-with-apigw \
--runtime python3.8 \
--role "arn:aws:iam::760182048326:role/translate-function-role" \
--handler translate-function-with-apigw.lambda_handler \
--zip-file fileb://translate-function-with-apigw.zip
{
"FunctionName": "translate-function-with-apigw",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function-with-apigw",
"Runtime": "python3.8",
"Role": "arn:aws:iam::760182048326:role/translate-function-role",
"Handler": "translate-function-with-apigw.lambda_handler",
"CodeSize": 462,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2020-05-04T09:48:09.842+0000",
"CodeSha256": "NPM1vqsoCFi8HwNW5DdMNMq6gRWzgV6EA0fcLiVblzE=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "cc6b2ba0-eb44-4897-b6c5-1709f8d49ef4",
"State": "Active",
"LastUpdateStatus": "Successful"
}
API 作成
リソースを作成
ID も確認する。
$ aws apigateway create-rest-api --name translate-api
{
"id": "xq5is7wlmc",
"name": "translate-api",
"createdDate": "2020-05-04T19:51:18+09:00",
"apiKeySource": "HEADER",
"endpointConfiguration": {
"types": [
"EDGE"
]
}
}
$ aws apigateway get-resources --rest-api-id xq5is7wlmc
{
"items": [
{
"id": "ebymz9abo0",
"path": "/"
}
]
}
子リソースを作成
$ aws apigateway create-resource \
--rest-api-id xq5is7wlmc \
--parent-id ebymz9abo0 \
--path-part translate
{
"id": "k8hfnw",
"parentId": "ebymz9abo0",
"pathPart": "translate",
"path": "/translate"
}
メソッドを作成
$ aws apigateway put-method \
--rest-api-id xq5is7wlmc \
--resource-id k8hfnw \
--http-method GET \
--authorization-type NONE
{
"httpMethod": "GET",
"authorizationType": "NONE",
"apiKeyRequired": false
}
$ aws apigateway put-integration \
--rest-api-id xq5is7wlmc \
--resource-id k8hfnw \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function-with-apigw/invocations"
{
"type": "AWS_PROXY",
"httpMethod": "POST",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function-with-apigw/invocations",
"passthroughBehavior": "WHEN_NO_MATCH",
"timeoutInMillis": 29000,
"cacheNamespace": "k8hfnw",
"cacheKeyParameters": []
}
$ aws apigateway put-method-response \
--rest-api-id xq5is7wlmc \
--resource-id k8hfnw \
--http-method GET \
--status-code 200 \
--response-models '{"application/json": "Empty"}'
{
"statusCode": "200",
"responseModels": {
"application/json": "Empty"
}
}
API Gateway への 権限付与
$ aws lambda add-permission \
--function-name translate-function-with-apigw \
--statement-id 72e0a706-02e8-479f-affb-0a2dcc5d4a29 \
--action "lambda:InvokeFunction" \
--principal apigateway.amazonaws.com
{
"Statement": "{\"Sid\":\"72e0a706-02e8-479f-affb-0a2dcc5d4a29\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function-with-apigw\"}"
}
デプロイ
$ aws apigateway create-deployment \
--rest-api-id xq5is7wlmc \
--stage-name dev
{
"id": "hq4jn2",
"createdDate": "2020-05-04T20:08:33+09:00"
}
動作確認
$ curl https://xq5is7wlmc.execute-api.ap-northeast-1.amazonaws.com/dev/translate?input_text=%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEAPI%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E3%81%A7%E3%81%99
{"output_text": "This is my first API call"}
所感
- メソッド作成時、統合タイプが Lambda 関数 にはなっているものの、Lambda プロキシ統合の使用が有効になっていないがためにきちんと動かず結構詰まった
put-integration
のtype
はAWS_PROXY
にする
- マネジメントコンソールから作った API と同じになるように
put-integration
やらput-method-response
をとりあえず実行したので、そのあたりの本質はまだ理解できていない
参考
2020-05-05(火)
JAWS-UG 初心者支部&千葉支部 #26 新人さん歓迎!ハンズオン<(オンライン) を CLI でやってみる (ハンズオン 3 編) #jawsug_bgnr
S3 バケット作成
$ aws s3 mb s3://20200505-transcribe-input-mfjt
make_bucket: 20200505-transcribe-input-mfjt
$ aws s3 mb s3://20200505-transcribe-output-mfjt
make_bucket: 20200505-transcribe-output-mfjt
Lambda Function 作成
OutpuBucketName
は自分のバケット名に変更しておく。
import json
import urllib.parse
import boto3
import datetime
s3 = boto3.client('s3')
transcribe = boto3.client('transcribe')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
try:
transcribe.start_transcription_job(
TranscriptionJobName= datetime.datetime.now().strftime("%Y%m%d%H%M%S") + '_Transcription',
LanguageCode='en-US',
Media={
'MediaFileUri': 's3://' + bucket + '/' + key
},
OutputBucketName='20200505-transcribe-output-mfjt'
)
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
ロールは相変わらず流用で。
$ zip transcribe-function.zip transcribe-function.py
adding: transcribe-function.py (deflated 48%)
$ aws lambda create-function \
--function-name transcribe-function \
--runtime python3.8 \
--role "arn:aws:iam::760182048326:role/translate-function-role" \
--handler transcribe-function.lambda_handler \
--zip-file fileb://transcribe-function.zip
{
"FunctionName": "transcribe-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:transcribe-function",
"Runtime": "python3.8",
"Role": "arn:aws:iam::760182048326:role/translate-function-role",
"Handler": "transcribe-function.lambda_handler",
"CodeSize": 667,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2020-05-05T08:36:23.606+0000",
"CodeSha256": "Ce79ystMNCxNtMV5JNg1cBs/wsPQZNBgU/EQ9y7ftIk=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "0406316d-82c6-4c2e-b315-d56b5e1f9ddd",
"State": "Active",
"LastUpdateStatus": "Successful"
}
イベント作成
マネジメントコンソールからの場合は設計図の使用からで大丈夫っぽいけど、CLI だと細かく設定が必要らしい。
Lambda Function への権限設定
$ aws lambda add-permission \
--function-name transcribe-function \
--statement-id s3-put-event \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::20200505-transcribe-input-mfjt
{
"Statement": "{\"Sid\":\"s3-put-event\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:760182048326:function:transcribe-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::20200505-transcribe-input-mfjt\"}}}"
}
$ aws lambda get-policy --function-name transcribe-function
{
"Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"default\",\"Statement\":[{\"Sid\":\"s3-put-event\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:760182048326:function:transcribe-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::20200505-transcribe-input-mfjt\"}}}]}",
"RevisionId": "be76518e-5680-4436-8c7a-6bc36ee78573"
}
S3 へのイベント追加
$ aws s3api put-bucket-notification-configuration \
--bucket 20200505-transcribe-input-mfjt \
--notification-configuration '{"LambdaFunctionConfigurations": [{"LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:transcribe-function", "Events": ["s3:ObjectCreated:Put"]}]}'
$ aws s3api get-bucket-notification-configuration --bucket 20200505-transcribe-input-mfjt
{
"LambdaFunctionConfigurations": [
{
"Id": "MTlhZThmYTItZGE3Mi00ZTM1LWE2YzktZWFkYjRjM2JmYmRk",
"LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:transcribe-function",
"Events": [
"s3:ObjectCreated:Put"
]
}
]
}
ポリシーのアタッチ
$ aws iam attach-role-policy \
--role-name translate-function-role \
--policy-arn "arn:aws:iam::aws:policy/AmazonS3FullAccess"
$ aws iam attach-role-policy \
--role-name translate-function-role \
--policy-arn "arn:aws:iam::aws:policy/AmazonTranscribeFullAccess"
動作確認
$ aws s3 cp HelloEnglish-Joanna.0aa7a6dc7f1de9ac48769f366c6f447f9051db57.mp3 s3://20200505-transcribe-input-mfjt
upload: ./HelloEnglish-Joanna.0aa7a6dc7f1de9ac48769f366c6f447f9051db57.mp3 to s3://20200505-transcribe-input-mfjt/HelloEnglish-Joanna.0aa7a6dc7f1de9ac48769f366c6f447f9051db57.mp3
$ aws transcribe list-transcription-jobs
{
"TranscriptionJobSummaries": [
{
"TranscriptionJobName": "20200505090252_Transcription",
"CreationTime": "2020-05-05T18:02:53.280000+09:00",
"StartTime": "2020-05-05T18:02:53.325000+09:00",
"CompletionTime": "2020-05-05T18:04:52.861000+09:00",
"LanguageCode": "en-US",
"TranscriptionJobStatus": "COMPLETED",
"OutputLocationType": "CUSTOMER_BUCKET"
}
]
}
$ aws transcribe get-transcription-job --transcription-job-name 20200505090252_Transcription
{
"TranscriptionJob": {
"TranscriptionJobName": "20200505090252_Transcription",
"TranscriptionJobStatus": "COMPLETED",
"LanguageCode": "en-US",
"MediaSampleRateHertz": 44100,
"MediaFormat": "mp3",
"Media": {
"MediaFileUri": "s3://20200505-transcribe-input-mfjt/HelloEnglish-Joanna.0aa7a6dc7f1de9ac48769f366c6f447f9051db57.mp3"
},
"Transcript": {
"TranscriptFileUri": "https://s3.ap-northeast-1.amazonaws.com/20200505-transcribe-output-mfjt/20200505090252_Transcription.json"
},
"StartTime": "2020-05-05T18:02:53.325000+09:00",
"CreationTime": "2020-05-05T18:02:53.280000+09:00",
"CompletionTime": "2020-05-05T18:04:52.861000+09:00",
"Settings": {
"ChannelIdentification": false,
"ShowAlternatives": false
}
}
}
$ aws s3 cp s3://20200505-transcribe-output-mfjt/20200505090252_Transcription.json - | jq '.results | .transcripts'
[
{
"transcript": "Hello. Do you speak a foreign language? One language is never enough."
}
]
参考
2020-05-10(日)
JAWS-UG 初心者支部&千葉支部 #26 新人さん歓迎!ハンズオン<(オンライン) を CLI でやってみる (ハンズオン 3' 編) #jawsug_bgnr
ハンズオン 1 編、ハンズオン 2 編、ハンズオン 3 編の続き。
2 つめの S3 バケットまではハンズオン 3 編を使い回しで。ただし、前回の分は削除してしまったので、改めて作成。
Lambda Function 作成
2 つめのバケットに PUT されたことをきっかけに動く Lambda Function を作成 (後述するけど、これでは動かなかった)。Python で書いたことがないので気持ち悪いところとかあるのかもしれないけれど、とりあえずは動けばいいや的な。
import json
import urllib.parse
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
s3_obj = s3.get_object(Bucket=bucket, Key=key)
s3_json = json.loads(s3_obj['Body'].read())
translate = boto3.client('translate')
input_text = s3_json['results']['transcripts']
response = translate.translate_text(
Text = input_text,
SourceLanguageCode = 'en',
TargetLanguageCode = 'ja'
)
output_text = response['TranslatedText']
return {
'statusCode': 200,
'body': json.dumps({
'output_text': output_text
})
}
$ zip translate-function.zip translate-function.py
adding: translate-function.py (deflated 51%)
$ aws lambda create-function \
--function-name translate-function \
--runtime python3.8 \
--role "arn:aws:iam::760182048326:role/translate-function-role" \
--handler translate-function.lambda_handler \
--zip-file fileb://translate-function.zip
{
"FunctionName": "translate-function",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function",
"Runtime": "python3.8",
"Role": "arn:aws:iam::760182048326:role/translate-function-role",
"Handler": "translate-function.lambda_handler",
"CodeSize": 573,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2020-05-10T10:06:48.639+0000",
"CodeSha256": "cMOe2mMvBRbkGApMIgK/7vYPdRj60c40C0i1O4MITvI=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "b0813324-c726-481f-b2d3-5a0137e5443b",
"State": "Active",
"LastUpdateStatus": "Successful"
}
2 つ目の S3 バケットへのイベント作成
Lambda Function への権限設定
$ aws lambda add-permission \
--function-name translate-function \
--statement-id s3-put-event \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::20200510-transcribe-output-mfjt
{
"Statement": "{\"Sid\":\"s3-put-event\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::20200510-transcribe-output-mfjt\"}}}"
}
S3 へのイベント追加
$ aws s3api put-bucket-notification-configuration \
--bucket 20200510-transcribe-output-mfjt \
--notification-configuration '{"LambdaFunctionConfigurations": [{"LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:translate-function", "Events": ["s3:ObjectCreated:Put"]}]}'
$ aws s3api get-bucket-notification-configuration --bucket 20200510-transcribe-input-mfjt
{
"LambdaFunctionConfigurations": [
{
"Id": "NWRjZTc3NTgtZWE1Ny00NGFlLTliNTctN2I0ZTEwYWI3MjE4",
"LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:760182048326:function:transcribe-function",
"Events": [
"s3:ObjectCreated:Put"
]
}
]
}
動作確認
どこで確認すればいいのか分からなかったけれど、CloudWatch Logs で確認できるようだったので今回はそこで。このあたりから CLI 縛りがきつくなってきたので、普通にマネジメントコンソール経由で操作していた。
[ERROR] TypeError: list indices must be integers or slices, not str
Traceback (most recent call last):
File "/var/task/translate-function.py", line 15, in lambda_handler
input_text = s3_json['results']['transcripts']
JSON の配列の参照の仕方が間違っていたので Lambda Function を修正。ついでに翻訳結果のレスポンスも CloudWatch Logs で確認できるように修正*1。
import json
import urllib.parse
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
s3_obj = s3.get_object(Bucket=bucket, Key=key)
s3_json = json.loads(s3_obj['Body'].read())
translate = boto3.client('translate')
input_text = s3_json['results']['transcripts'][0]['transcript']
response = translate.translate_text(
Text = input_text,
SourceLanguageCode = 'en',
TargetLanguageCode = 'ja'
)
output_text = response['TranslatedText']
print(output_text)
return {
'statusCode': 200,
'body': json.dumps({
'output_text': output_text
})
}
再度 MP3 ファイルを PUT したら、CloudWatch Logs にこんにちは。外国語を話しますか?1つの言語では決して十分ではありません。
と出力されたので上手く動いたことが確認できた。
Lambda Function 単体での動作確認は、イベントテンプレートの s3-put を流用して以下のようなテストイベントを作成すれば実行できた。
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "ap-northeast-1",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "20200510-transcribe-output-mfjt",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::20200510-transcribe-output-mfjt"
},
"object": {
"key": "20200510100920_Transcription.json"
}
}
}
]
}
サーバレスでやっていると、クラウド活用している感がより高まって楽しくなってくる。
*1 というか、ここまでの構成では確認する術がなかった