雑学

どーも!

たかぽんです!

今回はaws cliを使用して、S3から動画ファイルの内容をいい感じにcsvに落とし込んでみます...!

今回行うこと

S3に動画をたくさん配置して、その動画の解像度情報などを一覧でばば〜っと出す...といったことができるとちょっと嬉しいですよね...!

今回、それをaws cliとffprove, jqコマンドを使ってやってみます...!

ただし...

S3のファイルを一度localに持ってくる必要があります...(ファイルサイズと

事前に適当なS3に動画を配置しておきました。

object keyが階層になっていることも想定して、一つだけフォルダを追加しておきます。

これで事前準備はOKです。

AWS CLIでS3の情報を確認する

さて、まずはAWS CLIで先程のバケットの動画全ての情報を取得してみます。

aws cliのインストールは以下で解説しているので、まだインストールしていない方は是非ご一読ください。

例えばバケット名が"takapon-test-bucket"の場合、以下で取得が可能です。

(base) taka@Taka aws % aws s3 ls s3://takapon-test-bucket --recursive --human --sum
2021-07-04 05:11:28    6.9 MiB test.mov
2021-07-04 05:11:45  364.9 MiB test.mp4
2021-07-04 04:42:40    0 Bytes test1/
2021-07-04 05:13:31    3.8 MiB test1/test1-test.mov
2021-07-04 05:13:50   27.8 MiB test1/test1-test1.mov
2021-07-04 05:14:06    2.9 MiB test1/test1-test2.mov
2021-07-04 05:12:03   12.1 MiB test2.mov
2021-07-04 05:12:20    8.8 MiB test3.mov
2021-07-04 05:12:34    5.3 MiB test4.mov
2021-07-04 05:13:11  268.5 MiB test5.mov

Total Objects: 10
   Total Size: 700.8 MiB

これでファイルサイズ、登録日時、動画名が取得できます。

また、-humanはファイルサイズが読みやすく(Byteでの表示でなく、ちゃんとそれっぽい値に変換して表示してくれる)なり、--sumは最後に累計オブジェクト数や合計のファイルサイズを表示してくれます。

--recursiveオプションは再起的に...つまり、指定されているフォルダ以下のファイル全てを取得できます。

もし上記コマンド群をつけないで実行するとこんな感じになります。

(base) taka@Taka aws % aws s3 ls s3://takapon-test-bucket
                           PRE test1/
2021-07-04 05:11:28    7256612 test.mov
2021-07-04 05:11:45  382587385 test.mp4
2021-07-04 05:12:03   12637764 test2.mov
2021-07-04 05:12:20    9179000 test3.mov
2021-07-04 05:12:34    5524912 test4.mov
2021-07-04 05:13:11  281584938 test5.mov

比較すると、ファイルサイズに単位がつかず、バイトでの表示になり、"test1/"以下の値は表示されていません。

また、最後のtotal等も表示されていませんね。

基本的な情報は上記で取得可能です。

この時点ではファイルの実体をダウンロードしているわけでもないので、時間もかからず実行が可能です。

ただ、今回はファイルの解像度も取得したいです...!

そのため、一度ダウンロードします。(そのため、めちゃくちゃたくさん動画をホストしている...といった場合はちょっと非現実的になってしまいます...)

ダウンロードはローカルに保存してしまいましょう。

ファイル数が多い場合や、大切なデータの場合はlocalに持ってくることになるので気をつけてください。

(base) taka@Taka aws % ls
(base) taka@Taka aws % aws s3 cp s3://takapon-test-bucket . --recursive
download: s3://takapon-test-bucket/test1/test1-test2.mov to test1/test1-test2.mov
download: s3://takapon-test-bucket/test4.mov to ./test4.mov
download: s3://takapon-test-bucket/test2.mov to ./test2.mov
download: s3://takapon-test-bucket/test1/test1-test.mov to test1/test1-test.mov
download: s3://takapon-test-bucket/test3.mov to ./test3.mov
download: s3://takapon-test-bucket/test1/test1-test1.mov to test1/test1-test1.mov
download: s3://takapon-test-bucket/test.mov to ./test.mov
download: s3://takapon-test-bucket/test.mp4 to ./test.mp4
download: s3://takapon-test-bucket/test5.mov to ./test5.mov
(base) taka@Taka aws % ls
test.mov	test.mp4	test1		test2.mov	test3.mov	test4.mov	test5.mov

できました!

aws cliでの作業は一旦ここまでです!

次はffprobeで各種動画の情報を取得していきます...!

ffprobeコマンドを使って動画の解像度、bitrateをjsonで取得する

さて、今回は動画の解像度とbitrateを取得してみようと思います。

ffprobeコマンドはffmpegをインストールするとついてくるのですが、動画のさまざまな情報を取得できるコマンドになっています。

ffmpegのインストールは以下で解説しているのでよければそちらもご覧ください。

今回、ffprobeコマンドの詳細は割愛しますが、筆者が実際に辿り着いたコマンん度は以下です。

find . -type f -not -name '*json' -not -name '*csv' | xargs -n 1 ffprobe -loglevel quiet -select_streams v:0 -show_entries format=filename,bit_rate,size:stream=width,height -of json > output.json

簡単に説明しておくと、カレントディレクトリ以下のファイル全てに対してffprobeを適応しています。

また、後でjsonやcsvファイルを作るんですが、それらに対してffprobeをかけるとjsonが変になってしまうので、除外して適応するようにしています。

実際に出力される内容は以下です。

(base) taka@Taka aws % find . -type f | xargs -n 1 ffprobe -loglevel quiet -select_streams v:0 -show_entries format=filename,bit_rate,size:stream=width,height -of json
{
    "programs": [

    ],
    "streams": [
        {
            "width": 1968,
            "height": 1668
        }
    ],
    "format": {
        "filename": "./test.mov",
        "size": "7256612",
        "bit_rate": "1468454"
    }
}
.....
.....
.....
.....
{
    "programs": [

    ],
    "streams": [
        {
            "width": 1968,
            "height": 1668
        }
    ],
    "format": {
        "filename": "./test2.mov",
        "size": "12637764",
        "bit_rate": "1591323"
    }
}

"streams"の項目に動画のwidth, height, "format"の項目にファイルの名前(パス), ファイルサイズ(byte), bitrateが表示されます。

ffprobeコマンドを修正すれば、他にも値を追加することは可能です。

(今回は詳細は割愛しますが...別途ffprobeの解説記事...作れれば作りますね...!)

今回、わかりやすいようにjsonにして一度保存しておきます。

ほとんど一緒ですが、"> output.json"を追加してjsonファイルとして書き出しましょう。

find . -type f -not -name '*json' -not -name '*csv' | xargs -n 1 ffprobe -loglevel quiet -select_streams v:0 -show_entries format=filename,bit_rate,size:stream=width,height -of json > output.json

実行後、以下のように動画ファイルと別で"output.json"のファイルが作られればOKです。

(base) taka@Taka aws % ls
output.json	test.mov	test.mp4	test1		test2.mov	test3.mov	test4.mov	test5.mov

さて、これでffprobeを用いて動画の解像度, ビットレートを取得することができました。

最後にjsonからcsvに変換していきます。

csvとして整形する

さて、整形をする際にはjqコマンドを使用します。

先程のoutput.jsonを入力として、jqコマンドで必要な情報を含んだcsvに変換してあげます。

cat output.json | jq -r '.streams | [inputs]' | jq -r '.[] | [.format.filename, .streams[].width, .streams[].height, .format.size, .format.bit_rate]|@csv' > fileinfo.csv

csvの整形に関しては先程のjsonの中身に合わせて、その内容を調節しています。

jqコマンドのインストール方法、細かい調整方法については以下の記事をご参考ください。

実際に実行すると...

(base) taka@Taka aws % cat output.json | jq -r '.streams | [inputs]' | jq -r '.[] | [.format.filename, .streams[].width, .streams[].height, .format.size, .format.bit_rate]|@csv'
"./test1/test1-test1.mov",2880,1800,"29105619","8227736"
"./test1/test1-test2.mov",2880,1800,"2990185","6322858"
"./test1/test1-test.mov",2880,1800,"3942265","10571438"
"./test.mp4",1920,1342,"382587385","17577765"
"./test5.mov",1280,720,"281584938","12937759"
"./test4.mov",1968,1668,"5524912","1484027"
"./test3.mov",1968,1668,"9179000","1659480"
"./test2.mov",1968,1668,"12637764","1591323"
(base) taka@Taka aws % cat output.json | jq -r '.streams | [inputs]' | jq -r '.[] | [.format.filename, .streams[].width, .streams[].height, .format.size, .format.bit_rate]|@csv' > fileinfo.csv
(base) taka@Taka aws % ls
fileinfo.csv	output.json	test.mov	test.mp4	test1		test2.mov	test3.mov	test4.mov	test5.mov
(base) taka@Taka aws %

このような形で、出力で","区切りで出力されます。

ただし、項目の名称(ファイル名、Width, Height, Size, bit_rate等)はcsvに入っていないので、後から追加してあげる必要があります。

出力はfileinfo.csvとして書き出しました。

では最後にnumbersで確認してみます。

実際に開くと上記のようになっています。

あとは一行追加し、そこに"ファイル名"等のカラム名を追加すればいい感じになります。

spreadシートへ持っていくなり、FileSizeやBitrateをMBに直すなり、フィルターかけるなり、あとは分析するために色々としてあげれば良いのかなと思います。

もし追加でファイルの情報が必要な場合はffprobeコマンドを調べて、追加すれば可能です(ただし、その後のjqコマンドも修正が必要ですが...)。

ffprobe, jqコマンドをある程度理解できていれば自由度高く動画の分析が可能かなと思います。

ただし...!

何度もお伝えしていますが、ファイルをそのままlocalへコピーする必要がある点は気をつけてください。

ファイル数が多かったりファイルサイズが異常に大きい....といった場合は時間がかかりますし、実際にサービスで使われているファイルになると重要な情報をlocalに持ってくることになりかねないので、それらの点で問題のない範囲で行うべきでしょう。

なんにしても、以上でS3から取得したファイルの解像度やbitrateをcsvとして落とし込むことができました!

まとめ

ただ、S3に一度putしている動画ファイルからファイル実体を取得せずに解像度のみ取得する方法がわからず...

filesizeくらいなら取得できますが...解像度やbitrateも...!となると、おそらく現状は不可能なのかな...?と思っています。

やるならばPUT前に調べておいて、PUT時にカスタムメタデータとして付与しておくのがベストなんでしょうね..orz

すでに溜め込み始めてしまったバケットはどこかのタイミングでバッチ等で解像度やbitrateの情報をメタデータ付与する作業をしてもいいのかも...?ですね。

案外こういうの需要ありそうな気がするんだけど...

S3側で対応してファイルに応じてそういう深堀したデータをデフォルトでつけて欲しい...

動画ともなるとlambdaで扱うのも時間制限が気になるので、なかなか扱いづらいですよね...

画像程度であればlambda側で解析してメタデータ付与みたいなのも楽そうですが...

まぁ、今は可能な範囲で対応していくしかないですね...

それでわ!

おすすめの記事