Pythonで動画のメタデータを取得する
Pythonで動画のメタデータを取得する 動画ファイルの管理をしていると、ファイル名や拡張子、フレームレート、音声の有無、ビットレートなどの情報をまとめて確認したい場面があります。本記事では、Pythonの ffmpeg […]
Filter by Category
Pythonで動画のメタデータを取得する 動画ファイルの管理をしていると、ファイル名や拡張子、フレームレート、音声の有無、ビットレートなどの情報をまとめて確認したい場面があります。本記事では、Pythonの ffmpeg […]
Pythonでファイル・ディレクトリを削除する 日付形式のディレクトリを管理していると古いデータを定期的に整理する必要が出てきます。特に画像ファイルなどの日々大量に生成されるデータを扱うシステムでは、ストレージの圧迫を防 […]
Pythonのコマンドラインで特定の関数のみを指定して実行する AWS Lambdaではプログラム実行時に関数を指定しますが、pythonコマンドは通常、ファイル単位で指定するのでそのままでは実行できません。そのためロー […]
PythonとGhostscriptでPDFを軽量化 書類の添付などでブラウザからPDFをアップロードする際に数MB以下にしないとアップロードできないことがありますが、印刷用に作成したPDFや複数画像を一枚にまとめたPD […]
AWS LambdaとS3、SNSでファイルのアップロードを自動通知 AWS Lambdaは特定の条件を満たすときにサーバーレスでPython(他のプログラミング言語も)を実行できるサービスです。トリガーを検知したときや […]
PythonとMoviePyで動画ファイルの指定時間ごとの分割を自動化 OpenCVなどで動画の処理を行う際に、1分毎の変化や10分毎に結果を見たいときに一連の動画から指定した時間毎に分割して切り出したいことがあります。 […]
OpenCVで動画ファイルの最終フレームを取得 PythonとOpenCVを使用して動画ファイルの最大フレーム数を取得する方法を解説をします。処理の確認用に取得した最大フレーム数とファイル名をソートして表示させます。 コ […]
GitHub CopilotをPyCharmで使用するまでの手順 GitHub Copilotは、プログラミングの効率を飛躍的に向上させるツールで、開発者にとって非常に便利なコーディングのサポートを提供します。本記事では […]
PyCharm 2023.2から追加されたBlackによるコード成形 Pythonのコード成形で人気のBlackがPyCharm 2023.2から環境設定画面で設定可能になりました。従来はpipなどでインストールしていま […]
Twitter APIの変更に関して 最近、Twitter APIのバージョンがアップデートされ、v1が廃止されました。これに伴い、開発者はv2への移行が必要となります。 Twitter v1の廃止 Twitter v1 […]
PyCharmで.envから環境変数を読み込む 環境変数を.envに書いて読み込ませる理由 Pythonの開発では、セキュリティや環境毎の設定、柔軟性などの理由から.envファイルに環境変数を書いて読み込ませる方法が推奨 […]
AWS Cloud9にPython3.9をインストール AWSのCloud9(Ubuntu)にはデフォルトでPython 3.6.9がインストールされています。 openaiに必要なpandasのインストール opena […]
AWSのCloud9を使ってPythonのプログラミング研修を開催 2022年11月から2023年2月までの期間で、群馬県庁職員を対象にしたDXを促進するためのPythonによるプログラミング研修を開催しました。現在、群 […]
AttributeError: module ‘numpy’ has no attribute ‘float’ numpyを使ったライブラリをコマンド実行した際に以下のエラ […]
PythonからDeepLのAPIを使って翻訳 最先端のAI技術を使った世界最高レベルの機械翻訳のDeepLをAPIで操作します。deeplのライブラリを使うとPythonで書く通常のPOSTのコードよりも記述量を少なく […]
rembgで背景を削除した画像を編集して元の画像と再合成 YouTubeにアップロードしたrembgで背景を削除する説明動画にコメントをいただいたので、rembgを使った画像処理の続編です。rembgで背景を削除した画像 […]
Rembgで画像から背景を削除 先日、SNSで見た画像の背景を削除して切り抜くPythonのライブラリを見つけたので早速試してみました。普段業務で画像の背景を処理することも多くソフトを使って背景を削除していたので、Pyt […]
MacにGoProをウェブカメラとして認識させてOpenCVで使う MacとGoProを繋ぎ、GoProをウェブカメラとして認識させてOpenCVに映像を入力します。今回は映像を取り込んで画面に表示するだけですが、Pyt […]
Raspberry PiにInsightFaceをインストールできなかった 顔検出や顔認証、属性判定ができるInsightFaceというライブラリを使ってRaspberry Piで属性判定に挑戦しましたが、結果的にRas […]
WindowsでPythonの仮想環境を構築 Pythonで開発するときはMac版のPyCharmを使用しているので仮想環境も自動でPyCharmが構築してくれるのですが、Apple SiliconのMacでは動かないラ […]
動画ファイルの管理をしていると、ファイル名や拡張子、フレームレート、音声の有無、ビットレートなどの情報をまとめて確認したい場面があります。本記事では、Pythonの ffmpeg
ライブラリを活用し、指定したディレクトリ内の動画ファイルのメタデータを抽出し、JSON形式で保存するスクリプトについて解説します。
コードはGitHubリポジトリにあげています。
PC: MacBook Pro (14, 2021)
OS: macOS Monterey 12.6.7
Python: 3.12.0
このスクリプトは以下の機能を備えています。
ffmpeg
を用いて各動画ファイルのメタデータを取得import json
import os
import ffmpeg
from typing import List, Dict, Any, Optional
# 対象のディレクトリのパスを指定
DIRECTORY_PATH = "/DIR/PATH"
OUTPUT_JSON = "metadata.json"
# 取得するファイルの拡張子を指定
SUPPORTED_EXTENSIONS = (".mp4", ".mkv", ".avi", ".mov", ".flv")
def list_files(directory_path: str) -> List[str]:
"""指定したディレクトリから指定した拡張子のファイル一覧を取得"""
try:
with os.scandir(directory_path) as entries:
filtered_files = [
entry.path
for entry in entries
if entry.is_file() and entry.name.lower().endswith(SUPPORTED_EXTENSIONS)
]
# ファイル名でソートして返す
return sorted(filtered_files, key=lambda x: os.path.basename(x).lower())
except FileNotFoundError:
print(f"ディレクトリ内にファイルがありません: {directory_path}")
except PermissionError:
print(f"アクセス権限がありません: {directory_path}")
return []
def calculate_frame_rate(stream: Dict[str, Any]) -> Optional[float]:
"""動画のストリームからフレームレートを計算"""
r_frame_rate = stream.get("r_frame_rate")
if not r_frame_rate:
return None
try:
numerator, denominator = map(int, r_frame_rate.split("/"))
return numerator / denominator if denominator != 0 else None
except (ValueError, ZeroDivisionError):
return None
def format_duration(duration: Optional[float]) -> str:
"""再生時間を 時:分:秒 形式に整形"""
if not duration:
return "Unknown"
total_seconds = int(duration)
hours, remainder = divmod(total_seconds, 3600)
minutes, seconds = divmod(remainder, 60)
if hours > 0:
return f"{hours}時間{minutes}分{seconds}秒"
elif minutes > 0:
return f"{minutes}分{seconds}秒"
return f"{seconds}秒"
def extract_metadata(entry_file: str) -> Optional[Dict[str, Any]]:
"""動画ファイルからメタデータを抽出"""
try:
# ffmpegでファイルのメタデータを取得
probe = ffmpeg.probe(entry_file)
format_info = probe.get("format", {})
streams = probe.get("streams", [])
# 音声ストリームの有無を確認
has_audio = any(stream["codec_type"] == "audio" for stream in streams)
# フレームレートを動画ストリームから計算
frame_rate = next(
(
calculate_frame_rate(stream)
for stream in streams
if stream.get("codec_type") == "video"
),
None,
)
# 再生時間を取得(秒単位)
try:
duration = float(format_info.get("duration", 0.0))
except (ValueError, TypeError):
duration = None
# メタデータを辞書で返す
return {
"file_name": os.path.basename(entry_file),
"extension": os.path.splitext(entry_file)[1].lower(),
"has_audio": has_audio,
"frame_rate": frame_rate,
"duration": format_duration(duration),
"bit_rate": format_info.get("bit_rate", "Unknown"),
}
except ffmpeg.Error as e:
print(f"ffmpegのエラーが発生しました {entry_file}: {e}")
except Exception as e:
print(f"予期しないエラーで失敗しました {entry_file}: {e}")
return None
def get_metadata(directory_path: str) -> List[Dict[str, Any]]:
"""指定したディレクトリ内のすべてのファイルのメタデータを取得"""
entry_files = list_files(directory_path)
return [
metadata
for entry_file in entry_files
if (metadata := extract_metadata(entry_file))
]
def save_to_json(file_path: str, data: List[Dict[str, Any]]) -> None:
"""メタデータをJSONファイルに保存"""
try:
with open(file_path, "w", encoding="utf-8") as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
print(f"{file_path}を保存しました")
except Exception as e:
print(f"保存に失敗しました: {e}")
def main(directory_path: str, output_filename: str):
"""ディレクトリ内の動画ファイルからメタデータを取得して出力"""
if not os.path.exists(directory_path):
print("ディレクトリがありませんでした")
return
# メタデータの取得
metadata_list = get_metadata(directory_path)
# JSONファイルに保存
save_to_json(output_filename, metadata_list)
if __name__ == "__main__":
main(DIRECTORY_PATH, OUTPUT_JSON)
import json
import os
import ffmpeg
from typing import List, Dict, Any, Optional
モジュール・ライブラリのインポート
# 対象のディレクトリのパスを指定
DIRECTORY_PATH = "/DIR/PATH"
OUTPUT_JSON = "metadata.json"
# 取得するファイルの拡張子を指定
SUPPORTED_EXTENSIONS = (".mp4", ".mkv", ".avi", ".mov", ".flv")
def list_files(directory_path: str) -> List[str]:
"""指定したディレクトリから指定した拡張子のファイル一覧を取得"""
try:
with os.scandir(directory_path) as entries:
filtered_files = [
entry.path
for entry in entries
if entry.is_file() and entry.name.lower().endswith(SUPPORTED_EXTENSIONS)
]
# ファイル名でソートして返す
return sorted(filtered_files, key=lambda x: os.path.basename(x).lower())
except FileNotFoundError:
print(f"ディレクトリ内にファイルがありません: {directory_path}")
except PermissionError:
print(f"アクセス権限がありません: {directory_path}")
return []
def calculate_frame_rate(stream: Dict[str, Any]) -> Optional[float]:
"""動画のストリームからフレームレートを計算"""
r_frame_rate = stream.get("r_frame_rate")
if not r_frame_rate:
return None
try:
numerator, denominator = map(int, r_frame_rate.split("/"))
return numerator / denominator if denominator != 0 else None
except (ValueError, ZeroDivisionError):
return None
def format_duration(duration: Optional[float]) -> str:
"""再生時間を 時:分:秒 形式に整形"""
if not duration:
return "Unknown"
total_seconds = int(duration)
hours, remainder = divmod(total_seconds, 3600)
minutes, seconds = divmod(remainder, 60)
if hours > 0:
return f"{hours}時間{minutes}分{seconds}秒"
elif minutes > 0:
return f"{minutes}分{seconds}秒"
return f"{seconds}秒"
def extract_metadata(entry_file: str) -> Optional[Dict[str, Any]]:
"""動画ファイルからメタデータを抽出"""
try:
# ffmpegでファイルのメタデータを取得
probe = ffmpeg.probe(entry_file)
format_info = probe.get("format", {})
streams = probe.get("streams", [])
# 音声ストリームの有無を確認
has_audio = any(stream["codec_type"] == "audio" for stream in streams)
# フレームレートを動画ストリームから計算
frame_rate = next(
(
calculate_frame_rate(stream)
for stream in streams
if stream.get("codec_type") == "video"
),
None,
)
# 再生時間を取得(秒単位)
try:
duration = float(format_info.get("duration", 0.0))
except (ValueError, TypeError):
duration = None
# メタデータを辞書で返す
return {
"file_name": os.path.basename(entry_file),
"extension": os.path.splitext(entry_file)[1].lower(),
"has_audio": has_audio,
"frame_rate": frame_rate,
"duration": format_duration(duration),
"bit_rate": format_info.get("bit_rate", "Unknown"),
}
except ffmpeg.Error as e:
print(f"ffmpegのエラーが発生しました {entry_file}: {e}")
except Exception as e:
print(f"予期しないエラーで失敗しました {entry_file}: {e}")
return None
ffmpeg
を使って動画ファイルからメタデータを抽出して辞書形式に整形def save_to_json(file_path: str, data: List[Dict[str, Any]]) -> None:
"""メタデータをJSONファイルに保存"""
try:
with open(file_path, "w", encoding="utf-8") as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
print(f"{file_path}を保存しました")
except Exception as e:
print(f"保存に失敗しました: {e}")
def main(directory_path: str, output_filename: str):
"""ディレクトリ内の動画ファイルからメタデータを取得して出力"""
if not os.path.exists(directory_path):
print("ディレクトリがありませんでした")
return
# メタデータの取得
metadata_list = get_metadata(directory_path)
# JSONファイルに保存
save_to_json(output_filename, metadata_list)
if __name__ == "__main__":
main(DIRECTORY_PATH, OUTPUT_JSON)
群馬県でPythonを使ったAIやソフトウェアを開発している株式会社ファントムが運営しています。