Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compuglobal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
from compuglobal.models.screencap import Screencap, ScreencapMoment
from compuglobal.models.stream import Stream, StreamOverlay
from compuglobal.models.subtitle import Subtitle
from compuglobal.models.timestamp import Timestamp

__title__ = "compuglobal"
__author__ = "MitchellAW"
__license__ = "MIT"
__version__ = "0.3.7"
__version__ = "0.3.8"

__all__ = [
"APIPageStatusError",
Expand All @@ -47,4 +48,5 @@
"Stream",
"StreamOverlay",
"Subtitle",
"Timestamp",
]
6 changes: 2 additions & 4 deletions compuglobal/models/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pydantic import Field

from compuglobal.models.base import BaseCompuGlobalModel
from compuglobal.models.timestamp import Timestamp


class Frame(BaseCompuGlobalModel):
Expand Down Expand Up @@ -32,10 +33,7 @@ def get_real_timestamp(self) -> str:
A readable timestamp for the frame in format `mm:ss`.

"""
seconds = int(self.timestamp / 1000)
minutes = int(seconds / 60)
seconds -= minutes * 60
return f"{minutes}:{seconds:02d}"
return Timestamp.get_real_timestamp(timestamp=self.timestamp)

def __str__(self) -> str:
"""Get the string representation of the Frame.
Expand Down
29 changes: 26 additions & 3 deletions compuglobal/models/screencap.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from compuglobal.models.episode import EpisodeMetadata
from compuglobal.models.frame import Frame
from compuglobal.models.subtitle import Subtitle
from compuglobal.models.timestamp import Timestamp


class ScreencapMoment(BaseCompuGlobalModel):
Expand All @@ -29,6 +30,17 @@ class ScreencapMoment(BaseCompuGlobalModel):
content: str = Field(alias="Content")
title: str = Field(alias="Title")

def get_real_timestamp(self) -> str:
"""Get a readable timestamp for the moments timestamp in format `mm:ss`.

Returns
-------
str
A readable timestamp in format `mm:ss`.

"""
return Timestamp.get_real_timestamp(self.timestamp)


class Screencap(BaseCompuGlobalModel):
"""A Screencap of an episode at a point in time of a TV Show.
Expand Down Expand Up @@ -58,18 +70,29 @@ class Screencap(BaseCompuGlobalModel):
max_timestamp: int = Field(alias="MaxTimestamp", ge=0)

def get_real_timestamp(self) -> str:
"""Get a readable timestamp for the frame in format "mm:ss".
"""Get a readable timestamp for the frame in format `mm:ss`.

Returns
-------
str
A readable timestamp for the frame in format `mm:ss`.

"""
return self.frame.get_real_timestamp()
return Timestamp.get_real_timestamp(timestamp=self.frame.timestamp)

def get_duration(self) -> int:
"""Get duration of screencap subtitles in milliseconds.

Returns
-------
int
Duration in milliseconds

"""
return Timestamp.get_subtitles_duration(self.subtitles)

def captions(self) -> list[str]:
"""Get a list of captions for the screencap from all subttiles.
"""Get a list of captions for the screencap from all subtitles.

Returns
-------
Expand Down
5 changes: 3 additions & 2 deletions compuglobal/models/subtitle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pydantic import Field

from compuglobal.models.base import BaseCompuGlobalModel
from compuglobal.models.timestamp import Timestamp


class Subtitle(BaseCompuGlobalModel):
Expand Down Expand Up @@ -41,7 +42,7 @@ def get_duration(self) -> int:
Returns
-------
int
The duration in milliseonds.
The duration in milliseconds.

"""
return self.end_timestamp - self.start_timestamp
return Timestamp.get_duration(start_timestamp=self.start_timestamp, end_timestamp=self.end_timestamp)
76 changes: 76 additions & 0 deletions compuglobal/models/timestamp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""Timestamp module with helper class for working with timestamps."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from compuglobal.models.subtitle import Subtitle


class Timestamp:
"""Helper class for working with timestamps."""

@staticmethod
def get_minutes_seconds(milliseconds: int) -> tuple[int, int]:
"""Get minutes and seconds from milliseconds.

Parameters
----------
milliseconds : int
The length of time in milliseconds

Returns
-------
tuple[int, int]
The minutes, and seconds as a tuple

"""
seconds = int(milliseconds / 1000)
minutes = int(seconds / 60)
seconds -= minutes * 60
return minutes, seconds

@staticmethod
def get_real_timestamp(timestamp: int) -> str:
"""Get a readable timestamp for the frame in format `mm:ss`.

Returns
-------
str
A readable timestamp for the frame in format `mm:ss`.

"""
minutes, seconds = Timestamp.get_minutes_seconds(timestamp)
return f"{minutes}:{seconds:02d}"

@staticmethod
def get_duration(start_timestamp: int, end_timestamp: int) -> int:
"""Get the duration of the subtitle in milliseconds.

Returns
-------
int
The duration in milliseconds.

"""
return end_timestamp - start_timestamp

@staticmethod
def get_subtitles_duration(subtitles: list[Subtitle]) -> int:
"""Get the duration between the start of the earliest subtitle, and the end of the latest subtitle.

Parameters
----------
subtitles : list[Subtitle]
The subtitles

Returns
-------
int
The duration in milliseconds

"""
start_timestamp = min(subtitle.start_timestamp for subtitle in subtitles)
end_timestamp = max(subtitle.end_timestamp for subtitle in subtitles)
return Timestamp.get_duration(start_timestamp, end_timestamp)
9 changes: 9 additions & 0 deletions tests/models/test_screencap.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ def test_screencap_moment_validate_invalid_timestamp(bad_timestamp: int) -> None
ScreencapMoment.model_validate(payload)


def test_screencap_moment_get_real_timestamp(screencap_moment: dict[str, Any]) -> None:
moment = ScreencapMoment.model_validate(screencap_moment)
assert moment.get_real_timestamp() == snapshot("18:38")


def test_screencap_validate_dump(screencap: Screencap) -> None:
dump = screencap.model_dump()
expected = Screencap.model_validate(dump)
Expand All @@ -72,6 +77,10 @@ def test_screencap_get_caption(screencap: Screencap) -> None:
)


def test_screencap_get_subtitles_duration(screencap: Screencap) -> None:
assert screencap.get_duration() == snapshot(7799)


def test_screencap_get_start(screencap: Screencap) -> None:
assert screencap.get_start() == 347055

Expand Down