S3に保存されている動画の尺をLambdaで確認する

2 min読了の目安(約2000字TECH技術記事

きっかけ

特にこれといった目的があった訳じゃないんですが、動画の尺を取得できると便利かなとふと思った。個人的な案件でS3にファイルが保存されていることが多かったのでS3を対象としてるけど、他のストレージにも流用できそうな形にできたらいいなと感じ、メモ代わりに方法を残しておく。

方法

Layerの追加

Layerに追加するためのzipファイルをローカル環境で作成

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

作成したZipファイルをLayerに追加します。
AWS CLIで設定やS3にアップロードしてから設定する方法がありますが、今回はコンソールからLayerを登録しました。

ffprobe
コンソール上でLayerレイヤーを登録

Lambdaコード

Layerを追加して、ffprobeコマンドを実行して動画尺情報を取り出すことができます。

/opt/bin/ffprobe -i "url" -hide_banner -show_entries format=duration

指定するURLはpresigned urlで一時的にダウンロード可能にします

サンプルコードはこちら(IAMロールを適切に設定してください)

import subprocess
import shlex
import boto3

s3_client = boto3.client('s3')
SIGNED_URL_TIMEOUT = 10

def lambda_handler(event, context):

    s3_source_bucket = xxxxxxxxxxxxxxxx
    s3_source_key = yyyyyyyyyyyyyyyy

    signed_url = s3_client.generate_presigned_url(
        'get_object',
        Params={'Bucket': s3_source_bucket, 'Key': s3_source_key},
        ExpiresIn=SIGNED_URL_TIMEOUT
    )

    ffprobe_cmd = "/opt/bin/ffprobe -i \"%s\" -hide_banner -show_entries format=duration" % signed_url
    command = shlex.split(ffprobe_cmd)
    p1 = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    duration = p1.stdout.decode().split("\n")[1].replace("duration=", '')

    return {
        'duration': duration
    }

レスポンスに以下のように尺情報(秒)が出力されます。

{
  "duration": "596.568000"
}

おわりに

ffprobeをLmabdaで使えるようにして、URLで動画ファイルをGetできるようにする方法はいろんなケースで利用できるでしょう。
あまり需要はないと思うけど、誰かの参考になるときがくれば