リモート会議の議事録の記入を自動化したい その3 - 音声ファイルからテキストを抽出編(Amazon Transcribe)


https://qiita.com/ShinyaNakayama/items/1e43bbdb8150c0d8f88c

https://qiita.com/ShinyaNakayama/items/d229fa061567b3b92e30

その１、その2の続きです。
今回は構成で言うと下記の部分を実装します。
数字で言うと4~6の部分です。
![スクリーンショット 2023-04-08 8.27.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778864/ef54ee44-c9d2-98eb-ed39-a568dd8b6c4a.png)
その1、その2より構成を多少変更しましたので確認ください。
Amazon Transccibeだけでは音声ファイルのアップロードをトリガーにテキストへの変換ができなかったためLambdaを実装しました。

1. PCからS3に手動で動画をアップロード
1. S3への動画ファイルのアップロードをトリガーにLambdaを実行
1. Lambdaで動画ファイルを音声ファイルに変換してS3の別のバケットに保存
1. S3への音声ファイルのアップロードをトリガーにLambdaを実行
1. LambdaでTranscribeジョブを実行する
1. 変換されたテキストをS3の別のバケットに保存
1. S3へのテキストファイルのアップロードをトリガーに別のAIツールを用いてテキストファイルを要約する(予定)

# S3の設定
やることは下記です。
前回同様イベント通知についてはLambda関数で設定するのでそちらで行います。

* バケットを作る
* イベント通知を設定する（Lambda関数の設定時に行う）

### バケットを作る
その2で動画と音声を保存するバケットはすでに作成したのでテキストを保存するバケットを作成しましょう。
それぞれのバケット名は下記のように設定したとして話を進めます。
バケット名だけ決めてあとは全てデフォルト設定で問題ありません。
video-20230402
audio-20230402
text-20230408

# Lambda関数の設定
やることは下記です。（順不同）
* Lamda関数のためのIAMポリシーの作成
* Lambda関数の作成
* トリガーの設定
* その他の設定
* コードの記述

### lambda関数のIAMロールの作成
S3への操作が必要なため必要な権限をアタッチしたIAMポリシーを作成しましょう。
また今回はAmazon Transcribeジョブを実行する必要があるためそのためのポリシーも必要になります。
下記のJSONを含めたIAMポリシーを作成しましょう。
~~~JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::audio-20230402",
                "arn:aws:s3:::audio-20230402/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::text-20230408/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "transcribe:StartTranscriptionJob",
                "transcribe:GetTranscriptionJob",
                "transcribe:ListTranscriptionJobs"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "<Lambda関数のARNを入れましょう>"
        }
    ]
}
~~~

### Lambda関数の作成
その2を参照してください。基本的に設定は同じです。

https://qiita.com/ShinyaNakayama/items/d229fa061567b3b92e30#lambda%E9%96%A2%E6%95%B0%E3%81%AE%E4%BD%9C%E6%88%90

### トリガーの設定
こちらもその2を参照してください。
イベントソースのバケットを間違えないようにしましょう。
今回は"audio-20230402"となります。

### その他の設定
こちらについてもその2を参照してください。
異なる部分のみ記載します。

##### 一般設定
音声ファイルの処理なのでメモリを1024MBにしています。
タイムアウトも短くしても良いと思います。
![スクリーンショット 2023-04-08 8.54.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778864/44597445-372d-009c-3c7e-d5ae939b8e1d.png)

##### 環境変数の編集
環境変数は下記に設定
![スクリーンショット 2023-04-08 8.55.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778864/94f5dcaf-95dd-e438-281d-65e38dacc2a2.png)

### コードの記述
コードは下記のように記載しました。
~~~PYTHON
import boto3
import datetime
import json
import re
import os
from urllib.parse import unquote_plus


def lambda_handler(event, context):
    print("Received event:", json.dumps(event, indent=2))
    
    transcribe = boto3.client('transcribe')
    s3 = boto3.client('s3')
    
    # Input and output bucket names
    input_bucket = os.environ['INPUT_BUCKET']
    output_bucket = os.environ['OUTPUT_BUCKET']
    
    # Get the input audio file from S3
    encoded_key = event['Records'][0]['s3']['object']['key']
    key = unquote_plus(encoded_key)
    audio_file_uri = f's3://{input_bucket}/{key}'
    
    print(f"Audio file URI: {audio_file_uri}")  # Add this line to log the audio file URI
    
    timestamp = datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
    transcription_job_name = f'Transcription-{os.path.splitext(key)[0]}-{timestamp}'
    transcription_job_name = re.sub(r'[^0-9a-zA-Z._-]', '_', transcription_job_name)


    # Job configuration
    job_name = transcription_job_name
    language_code = 'ja-JP' # Change this to the language code of your audio file

    # Start the transcription job
    transcribe.start_transcription_job(
        TranscriptionJobName=job_name,
        LanguageCode=language_code,
        MediaFormat='mp3',
        Media={
            'MediaFileUri': audio_file_uri
        },
        OutputBucketName=output_bucket
    )

    return {
        'statusCode': 200,
        'body': 'Transcription job started'
    }

~~~
前回同様print文はトラブルシュートのためにあります。
**print("Received event:", json.dumps(event, indent=2))**
上記はアップロードのイベントが読み込めているかの確認となります。

**print(f"Audio file URI: {audio_file_uri}")**
上記はS3に保存されている音声ファイルがのURIとなります。
表示されない場合は音声ファイルが読み取れていないことになります。

**language_code = 'ja-JP'**
今回は日本語なので言語を日本語に設定しています。環境変数として設定した方が良かった気がします。。。

https://docs.aws.amazon.com/ja_jp/transcribe/latest/dg/supported-languages.html

# 結果
成功した場合に上記のprint文でどのように表示されるのかを添付します。

![スクリーンショット 2023-04-08 9.13.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778864/8e6c73b0-cc93-f705-a1f1-f02251bbbf3b.png)

![スクリーンショット 2023-04-08 9.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778864/b2f7ebfe-6c82-ed8a-95ae-d8289e5f7faf.png)

# 結論
動画からテキストの変換までの変換ができましたので一旦これにて終了。
最後までご覧いただきありがとうございました。