diff --git a/requirements.txt b/requirements.txt index 8e8313d..5992771 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,3 +22,4 @@ openai==2.16.0 emoji==2.15.0 funasr==1.3.1 torchaudio==2.11.0 +pillow-heif==1.3.0 diff --git a/src/open_storyline/__init__.py b/src/open_storyline/__init__.py index a68927d..96feb16 100644 --- a/src/open_storyline/__init__.py +++ b/src/open_storyline/__init__.py @@ -1 +1,13 @@ -__version__ = "0.1.0" \ No newline at end of file +__version__ = "0.1.0" + +# Register the HEIF/HEIC opener with Pillow so that downstream nodes that read +# images via PIL.Image.open() (load_media, render_video, sampling_handler, ...) +# transparently support .heic / .heif files produced by iPhone cameras. +try: + from pillow_heif import register_heif_opener as _register_heif_opener + + _register_heif_opener() +except ImportError: + # pillow-heif is an optional dependency; if missing, .heic uploads will + # still be filtered out by the suffix whitelist with a clear log line. + pass diff --git a/src/open_storyline/mcp/sampling_handler.py b/src/open_storyline/mcp/sampling_handler.py index fd2bc6e..57e7c53 100644 --- a/src/open_storyline/mcp/sampling_handler.py +++ b/src/open_storyline/mcp/sampling_handler.py @@ -23,7 +23,7 @@ DEFAULT_FRAMES_PER_SEC = 3.0 GLOBAL_MAX_IMAGE_BLOCKS = 48 # Maximum total images allowed (video frames + images) to prevent payload overflow -IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".gif", ".tiff"} +IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".gif", ".tiff", ".heic", ".heif"} VIDEO_EXTS = {".mp4", ".mov", ".mkv", ".avi", ".webm", ".m4v"} diff --git a/src/open_storyline/nodes/core_nodes/generate_ai_transition.py b/src/open_storyline/nodes/core_nodes/generate_ai_transition.py index e13e817..d73a602 100644 --- a/src/open_storyline/nodes/core_nodes/generate_ai_transition.py +++ b/src/open_storyline/nodes/core_nodes/generate_ai_transition.py @@ -92,7 +92,7 @@ class GenerateAITransitionNode(BaseNode): ".mp4", ".mov", ".mkv", ".avi" } IMAGE_EXTS = { - ".jpg", ".jpeg", ".png", ".webp", ".bmp" + ".jpg", ".jpeg", ".png", ".webp", ".bmp", ".heic", ".heif" } DEFAULT_TRANSITION_DURATION = 5 diff --git a/src/open_storyline/nodes/core_nodes/load_media.py b/src/open_storyline/nodes/core_nodes/load_media.py index c9dc4d8..0dedf7c 100644 --- a/src/open_storyline/nodes/core_nodes/load_media.py +++ b/src/open_storyline/nodes/core_nodes/load_media.py @@ -17,7 +17,7 @@ ".mp4", ".mov", ".mkv", ".avi" } IMAGE_EXTS = { - ".jpg", ".jpeg", ".png", ".webp", ".bmp" + ".jpg", ".jpeg", ".png", ".webp", ".bmp", ".heic", ".heif" } def _image_metadata_from_path(path: Path) -> dict[str, Any]: diff --git a/src/open_storyline/nodes/core_nodes/render_video.py b/src/open_storyline/nodes/core_nodes/render_video.py index 2212a05..805843b 100644 --- a/src/open_storyline/nodes/core_nodes/render_video.py +++ b/src/open_storyline/nodes/core_nodes/render_video.py @@ -233,7 +233,7 @@ def build_media_id_to_path_map(load_media: Dict[str, Any]) -> Dict[str, str]: def is_image_file(path: str) -> bool: try: - return Path(path).suffix.lower() in {".png", ".jpg", ".jpeg", ".bmp", ".webp", ".tif", ".tiff"} + return Path(path).suffix.lower() in {".png", ".jpg", ".jpeg", ".bmp", ".webp", ".tif", ".tiff", ".heic", ".heif"} except Exception: return False diff --git a/src/open_storyline/utils/media_handler.py b/src/open_storyline/utils/media_handler.py index da837c7..ce35bdf 100644 --- a/src/open_storyline/utils/media_handler.py +++ b/src/open_storyline/utils/media_handler.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import Union -_MEDIA_EXTS_IMG = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"} +_MEDIA_EXTS_IMG = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".heic", ".heif"} _MEDIA_EXTS_VID = {".mp4", ".mov", ".avi", ".mkv", ".webm", ".m4v"} def scan_media_dir(media_dir: Union[Path, str]) -> dict: