Skip to content

util

Public accessible objects of that module.

load_mpls

PlayList

Bases: NamedTuple

Represents a playlist.

Attributes:

Name Type Description
name str

The name of the playlist.

times list[int]

The list of times associated with the playlist.

load_mpls

load_mpls(f: BinaryIO, fix_overlap: bool = True) -> list[PlayList]

Load and parse an MPLS (Blu-ray playlist) file.

Parameters:

Name Type Description Default
f BinaryIO

The file object representing the MPLS file.

required
fix_overlap bool

Whether to fix overlapping timestamps. Defaults to True.

True

Returns:

Type Description
list[PlayList]

A list of PlayList objects representing the playlists in the MPLS file.

Examples:

>>> [
>>>     PlayList(name="00014", times=[189000000, 194469213, 225901239, 249525465, 253620806]),
>>>     PlayList(name="00015", times=[189000000, 200779267, 223110326, 249510450, 253620806]),
>>> ]
Source code in src/encode_utils_cli/util/load_mpls.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def load_mpls(f: BinaryIO, fix_overlap: bool = True) -> list[PlayList]:
    """Load and parse an MPLS (Blu-ray playlist) file.

    Args:
        f: The file object representing the MPLS file.
        fix_overlap: Whether to fix overlapping timestamps. Defaults to True.

    Returns:
        A list of PlayList objects representing the playlists in the MPLS file.

    Examples:
        >>> [
        >>>     PlayList(name="00014", times=[189000000, 194469213, 225901239, 249525465, 253620806]),
        >>>     PlayList(name="00015", times=[189000000, 200779267, 223110326, 249510450, 253620806]),
        >>> ]
    """

    def int_be(data: bytes) -> int:
        funcs = {
            1: ord,
            2: lambda b: unpack(">H", b)[0],
            4: lambda b: unpack(">I", b)[0],
        }
        return funcs[len(data)](data)

    f.seek(8)
    addr_items, addr_marks = int_be(f.read(4)), int_be(f.read(4))
    f.seek(addr_items + 6)
    item_count = int_be(f.read(2))
    f.seek(2, SEEK_CUR)

    def read_item() -> PlayList:
        block_size = int_be(f.read(2))
        name = f.read(5).decode()
        f.seek(7, SEEK_CUR)
        times = [int_be(f.read(4)), int_be(f.read(4))]
        f.seek(block_size - 20, SEEK_CUR)
        return PlayList(name, times)

    items = [read_item() for _ in range(item_count)]

    f.seek(addr_marks + 4)
    mark_count = int_be(f.read(2))

    def read_mark() -> tuple[int, int]:
        f.seek(2, SEEK_CUR)
        index = int_be(f.read(2))
        time = int_be(f.read(4))
        f.seek(6, SEEK_CUR)
        return (index, time)

    for _ in range(mark_count):
        index, time = read_mark()
        if time > items[index].times[-2]:
            items[index].times.insert(-1, time)

    if fix_overlap:
        b = None
        for item in items:
            a, b = b, item.times
            if a and b[0] < a[-1] < b[-1]:
                a[-1] = b[0]
        if b is not None and len(b) > 1 and b[-1] - b[-2] < 90090:  # noqa: PLR2004
            b.pop()

    return items

source

source

source(video: Path) -> VideoNode

Load a video source using VapourSynth.

Parameters:

Name Type Description Default
video Path

The path to the video file.

required

Returns:

Name Type Description
VideoNode VideoNode

The loaded video source.

Source code in src/encode_utils_cli/util/source.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def source(video: Path) -> VideoNode:
    """Load a video source using VapourSynth.

    Args:
        video: The path to the video file.

    Returns:
        VideoNode: The loaded video source.
    """
    return (
        core.lsmas.LibavSMASHSource(source=video)
        if video.suffix == ".mp4"
        else core.lsmas.LWLibavSource(source=video)
    )

timeconv

seconds2ts

seconds2ts(s: float) -> str

Convert seconds to timestamp in the format hh:mm:ss.xxx.

Source code in src/encode_utils_cli/util/timeconv.py
 4
 5
 6
 7
 8
 9
10
def seconds2ts(s: float) -> str:
    """Convert seconds to timestamp in the format `hh:mm:ss.xxx`."""
    m = s // 60
    s %= 60
    h = m // 60
    m %= 60
    return f"{h:02.0f}:{m:02.0f}:{s:06.3f}"

ts2seconds

ts2seconds(ts: str) -> float

Convert timestamp hh:mm:ss.xxxx to seconds.

Source code in src/encode_utils_cli/util/timeconv.py
13
14
15
16
def ts2seconds(ts: str) -> float:
    """Convert timestamp `hh:mm:ss.xxxx` to seconds."""
    h, m, s = map(float, ts.split(":"))
    return h * 3600 + m * 60 + s

seconds2f

seconds2f(s: float, fps: Fraction) -> int

Convert seconds to frames.

Source code in src/encode_utils_cli/util/timeconv.py
19
20
21
def seconds2f(s: float, fps: Fraction) -> int:
    """Convert seconds to frames."""
    return round(s * fps)

ts2f

ts2f(ts: str, fps: Fraction) -> int

Convert a timestamp hh:mm:ss.xxxx in number of frames.

Source code in src/encode_utils_cli/util/timeconv.py
24
25
26
def ts2f(ts: str, fps: Fraction) -> int:
    """Convert a timestamp `hh:mm:ss.xxxx` in number of frames."""
    return seconds2f(s=ts2seconds(ts), fps=fps)