Skip to content

Commit

Permalink
feat: enhance AudioAsset and ImageAsset to support remote file (#19)
Browse files Browse the repository at this point in the history
* feat: enhance AudioAsset and ImageAsset to support remote file loading with storage options

* chore: bump version 0.1.0rc5 -> 0.1.0rc6
  • Loading branch information
leodiegues authored Nov 25, 2024
1 parent 3a48c6a commit 671279e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 7 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "mosaico"
version = "0.1.0rc5"
version = "0.1.0rc6"
description = "Open-source video generation framework"
authors = [
{ name = "Leonardo Diegues", email = "[email protected]" },
Expand Down
11 changes: 8 additions & 3 deletions src/mosaico/assets/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from mosaico.assets.base import BaseAsset
from mosaico.assets.utils import check_user_provided_required_keys
from mosaico.media import _load_file
from mosaico.types import PathLike


Expand Down Expand Up @@ -94,23 +95,27 @@ def from_path(
:param kwargs: Additional keyword arguments to the constructor.
:return: The assets.
"""
storage_options = kwargs.pop("storage_options", None)

if not check_user_provided_required_keys(kwargs, ["duration", "sample_rate", "sample_width", "channels"]):
audio_info = _extract_audio_info(path)
raw_audio = _load_file(path, storage_options=storage_options)
audio_info = _extract_audio_info(raw_audio)
kwargs.update(audio_info)

return super().from_path(
path, encoding=encoding, mime_type=mime_type, guess_mime_type=guess_mime_type, metadata=metadata, **kwargs
)

def slice(self, start_time: float, end_time: float) -> AudioAsset:
def slice(self, start_time: float, end_time: float, *, storage_options: dict[str, Any] | None = None) -> AudioAsset:
"""
Slices the audio asset.
:param start_time: The start time in seconds.
:param end_time: The end time in seconds.
:param storage_options: The storage options.
:return: The sliced audio asset.
"""
with self.to_bytes_io() as audio_file:
with self.to_bytes_io(storage_options=storage_options) as audio_file:
audio = AudioSegment.from_file(
file=audio_file,
sample_width=self.sample_width,
Expand Down
8 changes: 6 additions & 2 deletions src/mosaico/assets/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from mosaico.assets.base import BaseAsset
from mosaico.assets.utils import check_user_provided_required_keys
from mosaico.media import _load_file
from mosaico.positioning import AbsolutePosition, Position
from mosaico.types import PathLike

Expand Down Expand Up @@ -100,9 +101,12 @@ def from_path(
:param kwargs: Additional keyword arguments to the constructor.
:return: The assets.
"""
storage_options = kwargs.pop("storage_options", None)

if not check_user_provided_required_keys(kwargs, ["width", "height"]):
with Image.open(path) as img:
kwargs["width"], kwargs["height"] = img.size
raw_image = _load_file(path, storage_options)
with Image.open(io.BytesIO(raw_image)) as image:
kwargs["width"], kwargs["height"] = image.size

return super().from_path(
path, encoding=encoding, mime_type=mime_type, guess_mime_type=guess_mime_type, metadata=metadata, **kwargs
Expand Down
40 changes: 40 additions & 0 deletions tests/assets/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,43 @@ def test_image_asset_with_metadata(sample_image_data):
image_asset = ImageAsset.from_data(sample_image_data, metadata=metadata)

assert image_asset.metadata == metadata


# def test_image_asset_from_remote_path(mocker, sample_image_data):
# # Mock the _load_file function to simulate remote file loading
# mock_load_file = mocker.patch("mosaico.media._load_file")
# mock_load_file.return_value = sample_image_data

# remote_path = "https://f.i.uol.com.br/fotografia/2022/02/09/16444170036203cfeb9fbd1_1644417003_3x2_md.jpg"
# image_asset = ImageAsset.from_path(remote_path)

# assert image_asset.type == "image"
# assert image_asset.width == 100
# assert image_asset.height == 50
# assert image_asset.to_bytes() == sample_image_data


# def test_image_asset_from_remote_path_with_explicit_dimensions(mocker, sample_image_data):
# # Mock the _load_file function to simulate remote file loading
# mock_load_file = mocker.patch("mosaico.media._load_file")
# mock_load_file.return_value = sample_image_data

# remote_path = "https://f.i.uol.com.br/fotografia/2022/02/09/16444170036203cfeb9fbd1_1644417003_3x2_md.jpg"
# image_asset = ImageAsset.from_path(remote_path, width=300, height=150)

# assert image_asset.width == 300
# assert image_asset.height == 150
# assert image_asset.to_bytes() == sample_image_data


# def test_image_asset_from_remote_path_with_metadata(mocker, sample_image_data):
# # Mock the _load_file function to simulate remote file loading
# mock_load_file = mocker.patch("mosaico.media._load_file")
# mock_load_file.return_value = sample_image_data

# remote_path = "https://f.i.uol.com.br/fotografia/2022/02/09/16444170036203cfeb9fbd1_1644417003_3x2_md.jpg"
# metadata = {"author": "Test User", "created": "2023-01-01"}
# image_asset = ImageAsset.from_path(remote_path, metadata=metadata)

# assert image_asset.metadata == metadata
# assert image_asset.to_bytes() == sample_image_data
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 671279e

Please sign in to comment.