Thumb:

image.png

<aside> <img src="/icons/list-indent_gray.svg" alt="/icons/list-indent_gray.svg" width="40px" />

目次:

</aside>

Examples


""" MDK メディアモジュール
 
* メディア関連のユーティリティ関数群

Info:
    * Created : 2025-12-15 Tatsuya Yamagishi
    * Coding : Python 3.11.9 & PySide6
    * Author : Tatsuya Yamagishi [[email protected]]

Release Note:
    * v0.0.1 2025-12-15 Tatsuya Yamagishi
        * new
"""
NAME = 'Create MP4 from Sequence Folder'
VERSION = 'v0.0.1'

# ======================================= #
# Import libs
# ======================================= #
import os
import pathlib
import platform
import re
import subprocess
import typing

# ======================================= #
# Settings
# ======================================= #
MDK_VERSION_FFMPEG = 'ffmpeg-2025-12-10'

# ======================================= #
# functions
# ======================================= #
def create_mp4_from_sequence_dir(dirpath: str, fps: float = 24.0) -> str:
    """
    画像シーケンスフォルダからMP4を作成

    Args:
        dirpath (str): 画像シーケンスフォルダパス
        fps (float, optional): フレームレート. Defaults to 24.0.

    Returns:
        str: 作成したMP4ファイルパス
    """
    _mdk_path = pathlib.Path(os.environ['MDK_PATH'])

    if platform.system() == 'Windows':
        _ffmpeg = _mdk_path / f'tools/ffmpeg/win/{MDK_VERSION_FFMPEG}/bin/ffmpeg.exe'

    _seq_path, _start_frame = get_padded_sequence_path(dirpath)
    _mp4 = pathlib.Path(dirpath).with_suffix('.mp4')

    cmd = [
        _ffmpeg.as_posix(),
        "-framerate", str(fps),  # フレームレートの設定
        "-start_number", str(_start_frame),  # 開始フレーム番号
        "-i", _seq_path,  # 連番画像の指定(%04dで4桁の数字に対応)
        "-c:v", "libx264",
        "-vf", f"drawtext=text='%{{n}}+{_start_frame-1}':x=W-tw-10:y=H-th-10:fontcolor=white:fontsize=24",  # フレーム番号オーバーライド:開始フレーム番号を基準に
        "-pix_fmt", "yuv420p",
        _mp4.as_posix()
    ]

    print('# --------------------------------------- #')
    print('# MDK | Create MP4 from sequence directory')
    print('# --------------------------------------- #')
    print(f'MDK_PATH = {_mdk_path}')
    print(f'FFMPEG = {_ffmpeg}')
    print(f'cmd = {" ".join(cmd)}')

    if not _ffmpeg.exists():
        raise FileNotFoundError(f'FFMPEG not found: {_ffmpeg.as_posix()}')

    # Create mp4
    subprocess.run(cmd, check=True)
    print('>>> Create mp4 complete <<<')

    return _mp4.as_posix()

def get_padded_sequence_path(
        folder: str,
        extensions=('png', 'jpg', 'jpeg', 'tiff', 'tif', 'exr')
    ) -> typing.Optional[typing.Tuple[str, int]]:

    """
    フォルダ内の連番画像から
    - 区切り文字(_ / .)
    - 開始フレーム
    - paddingを自動判定し、ffmpeg 用 sequence パスを返す
    - Coding by ChatGPT

    Returns:
        (sequence_path, start_frame)
        
    Examples:
        >>> get_padded_sequence_path(r'test/test.1012.exr')
        >>> ('test/test.%04d.exr', 1012)
        >>> get_padded_sequence_path(r'test/test.12345678.exr')
        >>> ('test/test.%08d.exr', 12345678)
    """

    entries = []

    pattern = re.compile(
        rf"(.+?)([_\\.])(\\d+)\\.({'|'.join(extensions)})$",
        re.IGNORECASE
    )

    for name in os.listdir(folder):
        match = pattern.match(name)
        if match:
            base = match.group(1)
            sep = match.group(2)
            frame_str = match.group(3)
            ext = match.group(4).lower()

            entries.append({
                "base": base,
                "sep": sep,
                "frame": int(frame_str),
                "padding": len(frame_str),
                "ext": ext
            })

    if not entries:
        return None

    # 開始フレーム
    start_frame = min(e["frame"] for e in entries)

    # padding(最大桁数)
    padding = max(e["padding"] for e in entries)

    # 最も多く使われている separator を採用(安全)
    sep = max(set(e["sep"] for e in entries), key=lambda s: sum(x["sep"] == s for x in entries))

    # base / ext(最初のエントリを使用)
    base = entries[0]["base"]
    ext = entries[0]["ext"]

    pattern_str = f"%0{padding}d"
    sequence_path = os.path.join(folder, f"{base}{sep}{pattern_str}.{ext}")

    return sequence_path, start_frame

関連

無題

Apps

無題

資料