群馬県でPythonを使ったAIやシステムを開発しているファントム

Navigation
群馬県でPythonを使ったAIやシステムを開発しているファントム

群馬県でPythonを使ったAIやシステムを開発しているファントムです。企業の経営課題を最適なテクノロジーで解決します。テックブログではPythonを中心にプログラミングに役立つ情報を発信しています。

投稿を検索する


  • 株式会社ファントム コーポレートサイト

カテゴリー



  • AWS 16
  • Django 45
  • FastAPI 4
  • Flask 8
  • GCP 1
  • Information 37
  • Other 32
  • PHP 2
  • Python 93
  • Pythonista 3
  • Rust 1

タグ


Alembic API argparse Beautiful Soup black Channels charset CodeCommit datetime Django REST framework Docker enumerate f-string git GitHub glob Google Colaboratory i18n IAM Internship Jupyter Lambda Matplotlib Nginx OpenCV pandas PIL Pillow PostgreSQL PyCharm PyCon pyenv PyTorch Redis Rembg ReportLab requests S3 Sentry slack tqdm uWSGI venv Vue.js youtube
このサイトはreCAPTCHAによって保護されており、Googleのプライバシーポリシーと利用規約が適用されます。

© 2022 Fantom, Inc.

Hydra WordPress Theme by EckoThemes.

Published with WordPress.

Related Articles

Filter by Category

  • Python(93)
  • Django(45)
  • Information(37)
  • Other(32)
  • AWS(16)
  • Flask(8)
  • FastAPI(4)
  • Pythonista(3)
  • PHP(2)
  • GCP(1)
  • Rust(1)

Filter by Author

  • EIGHT (14)
  • hayai017 (2)
  • press (196)
Back to Latest Articles
Python

Pythonで動画のメタデータを取得する

Pythonで動画のメタデータを取得する 動画ファイルの管理をしていると、ファイル名や拡張子、フレームレート、音声の有無、ビットレートなどの情報をまとめて確認したい場面があります。本記事では、Pythonの ffmpeg […]

Posted on 21st 1月 2025 by press

Other

2024年に最も読まれた記事ランキング

2024年に最も読まれた記事ランキング あけましておめでとうございます2025年もどうぞよろしくお願いします ファントムは2025年も皆様のお役に立てるよう精進しますより一層のご支援、お引立てを賜りますようお願い申し上げ […]

Posted on 9th 1月 2025 by press

Other

git stashでコミット前の作業を退避する

git stashでコミット前の作業を退避する 開発の途中で別のブランチに切り替えたり、緊急の修正が必要になることも珍しくありません。そんなときに現在の変更はコミットせずに一時的に保存しつつ、変更前のクリーンな状態に戻し […]

Posted on 3rd 12月 2024 by press

AWS

AWS CLIでファイルをS3へアップロード

AWS CLIでファイルをS3へアップロード クラウドストレージへのファイルアップロードは、現代のシステム開発において欠かせない作業の一つです。特にAmazon S3はその高い信頼性と豊富な機能により、多くのプロジェクト […]

Posted on 24th 11月 2024 by press

Python

Pythonでファイル・ディレクトリを削除する

Pythonでファイル・ディレクトリを削除する 日付形式のディレクトリを管理していると古いデータを定期的に整理する必要が出てきます。特に画像ファイルなどの日々大量に生成されるデータを扱うシステムでは、ストレージの圧迫を防 […]

Posted on 9th 11月 2024 by press

AWS

GitHub Actionsで Lambdaにデプロイ失敗した原因を調査

GitHub Actionsで Lambdaにデプロイ失敗した原因を調査 GitHub ActionsでLambdaへデプロイ中に発生したエラーを調査し、適切なポリシーの追加と deploy.ymlへのコマンド追加で解消 […]

Posted on 5th 9月 2024 by press

AWS

GitHub ActionsでAWS Lambdaに自動デプロイ

GitHub ActionsでAWS Lambdaに自動デプロイ DevOpsの実践において、CI / CD(継続的インテグレーション / 継続的デリバリー)は欠かせない要素となっています。特に、クラウドサービスを活用し […]

Posted on 4th 9月 2024 by press

AWS

Pythonのコマンドラインで特定の関数のみを指定して実行する

Pythonのコマンドラインで特定の関数のみを指定して実行する AWS Lambdaではプログラム実行時に関数を指定しますが、pythonコマンドは通常、ファイル単位で指定するのでそのままでは実行できません。そのためロー […]

Posted on 2nd 9月 2024 by press

Python

PythonとGhostscriptでPDFを軽量化

PythonとGhostscriptでPDFを軽量化 書類の添付などでブラウザからPDFをアップロードする際に数MB以下にしないとアップロードできないことがありますが、印刷用に作成したPDFや複数画像を一枚にまとめたPD […]

Posted on 9th 6月 2024 by press

FastAPI

Alembicでheadが複数存在する時に発生するエラーの修正

Alembicでheadが複数存在する時に発生するエラーの修正 FastAPI, PostgreSQL, Alembicで開発中のプロジェクトで、alembic upgrade headコマンドでマイグレーションを実行し […]

Posted on 26th 4月 2024 by press

Other

Jetson NanoのWiFiモジュール取り付け手順

Jetson NanoのWiFiモジュール取り付け手順 Jetson NanoはNVIDIA社が提供するGPUを搭載した小型かつ低電力で動作する開発用ボードです。GPUを搭載しているのでCUDAを使って画像処理などの並列 […]

Posted on 21st 4月 2024 by press

Information

2024年度 長期インターンシップについて

2024年度 長期インターンシップについて For English page 概要 2024年度 インターンシップの募集を開始します。 募集内容 ・インターンシップ 募集職種 ・機械学習エンジニア・ウェブアプリケーション […]

Posted on 19th 4月 2024 by press

Information

Announcement about Internships for 2024

Announcement about Internships for 2024 日本語のページ Overview Recruitment for the 2024 internship program is now op […]

Posted on 19th 4月 2024 by press

Other

2023年に最も読まれた記事ランキング

2023年に最も読まれた記事ランキング あけましておめでとうございます2024年もどうぞよろしくお願いします ファントムは2024年も皆様のお役に立てるよう精進しますより一層のご支援、お引立てを賜りますようお願い申し上げ […]

Posted on 4th 1月 2024 by press

AWS

CodePipelineでCodeBuildのテストを自動化

CodePipelineでCodeBuildのテストを自動化 CodeCommitで管理しているリポジトリをCodeBuildでテストする場合は通常、手動でテストを実行させる必要がありますが、CodePipelineを使 […]

Posted on 12th 12月 2023 by press

AWS

AWS CodeCommitでプルリクエスト・マージ

AWS CodeCommitでプルリクエスト・マージ ソースコードの管理にはGitHubやGitLabを採用している方が多いかもしれませんが、AWSにもCodeCommitというサービスがあり、5人までは無料で5人以上で […]

Posted on 12th 12月 2023 by press

FastAPI

FastAPI + SQLAlchemy + Alembic + SQLiteでマイグレーション

FastAPI + SQLAlchemy + Alembic + SQLiteでマイグレーション FastAPIにはデータベースのマイグレーション機能はありませんが、Alembicというデータベースのマイグレーションツー […]

Posted on 5th 12月 2023 by press

AWS

AWS LambdaとS3、SNSでファイルのアップロードを自動通知

AWS LambdaとS3、SNSでファイルのアップロードを自動通知 AWS Lambdaは特定の条件を満たすときにサーバーレスでPython(他のプログラミング言語も)を実行できるサービスです。トリガーを検知したときや […]

Posted on 21st 11月 2023 by press

Other

GitHubリポジトリを別のOrganizationに移行

GitHubリポジトリを別のOrganizationに移行 非公開用のOrganization(組織)で管理していたリポジトリの公開範囲をプライベートから公開に変更するにあたって、リポジトリを別のOrganization […]

Posted on 20th 11月 2023 by press

Python

PythonとMoviePyで動画ファイルの指定時間ごとの分割を自動化

PythonとMoviePyで動画ファイルの指定時間ごとの分割を自動化 OpenCVなどで動画の処理を行う際に、1分毎の変化や10分毎に結果を見たいときに一連の動画から指定した時間毎に分割して切り出したいことがあります。 […]

Posted on 20th 11月 2023 by press

View Latest Posts
Python

Pythonで動画のメタデータを取得する


press
Pythonで動画のメタデータを取得する
Posted on 21st 1月 2025 by press
2024年度 インターンシップ 募集開始

Pythonで動画のメタデータを取得する

動画ファイルの管理をしていると、ファイル名や拡張子、フレームレート、音声の有無、ビットレートなどの情報をまとめて確認したい場面があります。本記事では、Pythonの ffmpeg ライブラリを活用し、指定したディレクトリ内の動画ファイルのメタデータを抽出し、JSON形式で保存するスクリプトについて解説します。

コードはGitHubリポジトリにあげています。

開発環境

PC: MacBook Pro (14, 2021)
OS: macOS Monterey 12.6.7
Python: 3.12.0

スクリプトの概要

このスクリプトは以下の機能を備えています。

  1. 指定したディレクトリ内の動画ファイルを検索
  2. ffmpeg を用いて各動画ファイルのメタデータを取得
  3. フレームレート、音声の有無、再生時間などの情報を整理
  4. 取得したメタデータをJSONファイルとして保存

動画のメタデータを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


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")
  • 下記の定数を指定
    • メタデータを取得するファイルがあるディレクトリ
    • 出力するjsonファイル名
    • 取得するファイルの拡張子
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
  • 動画のストリームからフレームレートを計算
  • 計算に失敗してエラーが発生した場合は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}")
  • 取得したメタデータをjson形式で保存
  • 保存に失敗した場合はエラーを返却
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)
  • 動画のメタデータをjson形式で保存するスクリプトを実行するメイン関数
ファントムYouTubeチャンネル

株式会社ファントムへのお問い合わせ

群馬県でPythonを使ったAIやソフトウェアを開発している株式会社ファントムが運営しています。




    press
    • FFmpeg
    • Share Article:
    • Twitter
    • Facebook
    • Pinterest
    • LinkedIn
    • Reddit

    Related Articles

    Python

    PyCharm 2023.2から追加されたBlackによるコード成形

    PyCharm 2023.2から追加されたBlackによるコード成形 Pythonのコード成形で人気のBlackがPyCharm 2023.2から環境設定画面で設定可能になりました。従来はpipなどでインストールしていま […]

    Posted on 13th 9月 2023 by press
    Python

    Pythonのf文字列を使った文字列の操作

    Pythonのf文字列を使った文字列の操作 Pythonのf文字列は{1}や{a}のように変数を{}(波括弧)で囲うことで、文字列の中に変数を挿入できるので直感的な記述ができるようになります。従来のように複数の変数や文字 […]

    Posted on 22nd 2月 2022 by press