📹

AWS S3 トリガーを使用して動画翻訳と字幕付きを作成する

2023/08/31に公開

概要

8月にMEGAZONE JAPANに入社しましたジョン・ジェユンと申します!

早速ですが、タイトルの通りに、AWS S3トリガーを使用して動画翻訳を作成してみました。

先日、本社(韓国)から会社関連の動画が共有されましたが、
その内容は韓国語で話されていたため、字幕が欲しいという日本のチームメンバーがいました。

うむ!🔥
AWSでは映像や言語関連のサービスを提供していることはわかっていたので、気軽に触ってみました。
その結果、この記事を書くきっかけとなりました。

Infrastructure

今回、作成するInfrastructureは以下のようになります。

Userが動画をS3にUploadすると、Lambdaが動くようにします。
Lambdaでは、動画をAmazon TranscribeでSRTを抽出し、そのFileをAmazon Translateで翻訳を行います。
最後に、翻訳されたSRTを動画に入れて、S3にUploadする仕組みとなります。

Outputとしては、以下の左のBeforeを、右のAfterのようにすることです。

Before After

この記事の流れは、
1。構築手順
2。ハマったポイント
3。感想
の順で書いてみました。

構築手順

今回の構築は基本Console上で行いました。では、以下の順で説明します。

1. Lambda作成
2. S3作成
3. Lambda functions作成
4. 動作確認

1. Lambda作成

Lambdaから作成します。
値は以下のように、NameとPythonの選択くらいです。

作成すると、Lambdaページは以下のようになります。

functionはS3 トリガー設定後に説明します。

2. S3作成

S3 Bucketを作成します。Nameを記入し、他のOptionsはDefaultのままでOKです。

S3 Bucketができたら、Ceate folderからvideo,srt,substitleを作成します。
それぞれの役割は以下のようになります。

YourBucket/video/ : 動画Uploadするトリガー用
YourBucket/srt/ : srt file保管用
YourBucket/substitle/ : 動画字幕付き保管用


なお、トリガー folderを設定してみます。
BucketのPropertiesにタグを切り替えます。

下にScrollすると、Event notifications(トリガー)ありますので、Eventを作成します。

Eventは以下のように、設定します。
Video folderにUpload(PUT)すると、「1. Lambda作成」で作成したLamdba functionを呼び出すことができます。


上記の設定で作成すると、以下のように見えると思います。

そして、Lambdaの中身を見ると、トリガーとして表れます。

3. Lambda functions作成

ここまでがS3 トリガーを使用してLambdaを呼び出すようになったので、
LambdaにS3の権限を付与する部分から説明します。

IAMのRolesに移動すると、「1. Lambda作成」で作成した時に作られたRoleがあると思います。
そのRole nameをクリックします。

Add permissionsのプルダウンからAttach policiesをクリックします。

S3で検索すると、色々表示されますが、S3FullAccessを選択し、Add permissionsをクリックし、Attachを行います。

これでS3の権限を付与できました。

Lambda functionsは次のように作成しました。
やっていることを簡単に説明します。
Amazon TranscribeでS3(video/)にUploadした.mp4の言語を識別し、srt fileをS3(srt/)に作成します。
そのsrt fileをAmazon Translateで翻訳版を作成します。
翻訳版のsrt fileをS3(video/)にある.mp4に入れて、S3(substitle/)にUploadします。

Codeを作成及び修正を行なうたびに、Deployしておきましょう。

次はffmpegをLayersに登録します。
まずは、自分の環境上に次のCommandを実行します。ffmpegが含まれたZipを作成します。

$ wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
$ tar xvf ffmpeg-release-amd64-static.tar.xz
$ mkdir -p ffmpeg/bin
$ cp ffmpeg-6.0-amd64-static/ffmpeg ffmpeg/bin/
$ cd ffmpeg
$ zip -r ../ffmpeg.zip .

こちらのZipを「2. S3作成」で作成したBucketにUploadしておきます。

LambdaのLayersに移動し、Layerを作成します。
先ほどffmpeg ZipをUploadしたObject URLを貼り付けて、作成します。

Layerの作成が終わったら、詳細ページにARNが表示(以下赤いボックス)されますが、それをCopyしておいてください。
(imageにあるVersionは気にしないでください。最初に作成されたら1となっているはずです)

Lambda functionに戻って、作成したLayerを登録しておきます。
Add Layerで、Specify an ARNを選択し、CopyしたARNを貼り付けて、Verifyまで行います。
その後Addをクリックし、Lambda functionにLayerを登録します。

Lambda functionのOverViewにはS3 トリガーとLayer(1)が表示されると思います。

最後にfunctionsのtimeoutだけ設定しておきます。
今回は1分で設定しておきました。

4. 動作確認

S3のVideoにSample動画をUploadします。

そのトリガーにより、同じタイミングでCloudWatch Logsが生成されることが確認できます。

Logsの中身を確認し、最後まで実行できたのが確認できたら、S3のsrt/とsubstitle/を確認してみます。
時間を見ると実行完了までに1分くらいかかっているようです。

動画の字幕付きFileが確認できたら、sample-substitle.mp4をDownloadして確認してみましょう。

試しに韓国語も対応してみました。 👍

補足ですが、CodeのDebugや動作確認のために、Configure test eventを設定しておきました。
TemplateはS3Putを選択し、bucket > nameにはBucket名と、object > keyにはvideo/{~.mp4}で設定しました。

ハマったポイント

ffmpeg layerについて

  • Lambdaでライブラリを使用する際、import以外の方法はあまり経験がありませんでした。通常、ffmpegをimportして動かしたところ、not foundエラーに結構ハマってしまいました。しかし、その後、パッケージングとlayerを使用して問題を解決しました。
    具体的には、ffmpegを含むカスタムlayerを作成し、Lambda関数でそのlayerを使用することで、必要なライブラリと実行Fileを提供しました。これにより、ライブラリが見つからないというエラーを回避し、スムーズにffmpegを使用して動作させることができました。
    この経験を通じて、Lambdaで外部ライブラリを使用する際には、パッケージングとlayerの活用が重要であることを学びました。

AWS translateとsrtについて

  • AWS translateにsrt fileを翻訳すると、srt formatが崩れることに気づきました。例えば、
    正:00:01:23,150 --> 00:01:27,880
    誤:00:01:23,150--> 00:01:27,880
    上記の誤のように、矢印の形が変わってしまい、ffmpegで動画に字幕を入れる際に、invalid dataエラーになりました。
    そのため、矢印formatを正しく修正するformat_subtitles()関数を作成して、解決しました。
    ちなみに、AWS translateを利用した翻訳なので、必要に応じて意訳は必要だと思いました。

感想

久々にAWSを触って楽しい時間を過ごしました。実際に動かしてみることで、今後どのように活用できるか、勉強になることや得られるものが多いでしょう。

今回は、Lambdaを使用して動画Fileを記録し、翻訳を行い、最終的には字幕を付けてみました。一方で、Lambda関数のスケーリングに関する部分が不足していたと感じました。

特に、TranscribeServiceのstart_transcription_jobという動画の記録に関連する処理は、記録(この場合はSRT形式の作成)に時間がかかる仕様でした。Lambda内で実行するため、ジョブの完了ステータスをget_transcription_jobを使用して取得し、完了するまでwhileループで待機させました。この方法で問題はありませんでしたが、このようなリアルタイムでの実行が適切かどうか、ずっと悩んでいました。
ちなみに、リアルタイムに実行できるstart_stream_transcriptionというイベントも存在しましたが、今回のような字幕対応には適用できませんでした。

Lambda関数のスケーリングに関する側面もまだまだ多く、今後も実際に触りながら理解を深めていきたいと考えています。🔥

Reference

AWS boto3 docs TranscribeService

AWS boto3 docs Translate

Sample video file

ffmpeg docs

lambda layer

Amazon S3 trigger to invoke a Lambda funtion

Lambda Layerの基本的な仕組みを確認する #reinvent

MEGAZONE株式会社 Tech Blog

Discussion