diff --git a/README.md b/README.md index e432593..d3451f2 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,53 @@ -# ComfyUI-AIA-BatchVideoDegrade +# ComfyUI-vid2frames -Small AIA custom node pack for applying cheap-phone/video-upload degradation to a -batched ComfyUI `IMAGE` tensor. +A small ComfyUI custom node package for selecting useful still frames from a decoded video frame batch. -Repository: https://github.com/Pmobilee/ComfyUI-vid2frames +## Node -## Nodes +### `AIA_SelectVideoFrame` -- `AIA_BatchDequality`: applies per-frame JPEG recompression, sensor-like noise, - and small brightness/color/contrast jitter while preserving batch shape. -- `AIA_SelectVideoFrame`: scores a decoded video frame batch and returns one - selected frame. The selector string supports `no face`, `blurry`, `moving`, - `static`, `flicker`, and `lighting`; empty or unknown selectors use best-still - scoring. Add an explicit rank such as `moving rank 2` or `lighting #3` to get - the next high-scoring frame for that category, with temporal spacing applied - so ranked picks do not cluster around the same moment. +Inputs: + +- `image`: ComfyUI `IMAGE` batch, usually decoded video frames. +- `selector`: text command describing the target frame type. + +Output: + +- A single-frame ComfyUI `IMAGE` batch. + +Supported selector modes: + +- Empty or unknown text: best still frame. +- `no face`: lowest face score while still preferring usable frames. +- `blurry`: softest reasonable frame. +- `moving`: strongest motion frame with blur and lighting penalties. +- `static`: low-motion sharp frame. +- `flicker` or `lighting`: strongest lighting fluctuation. + +Ranked variants are supported. For example, `moving rank 2` or `lighting #3` returns another high-scoring frame in the same category. Ranked picks apply temporal spacing so nearby frames from the same moment do not crowd out more useful alternatives. + +## How It Scores Frames + +The node computes: + +- Sharpness from Laplacian variance. +- Motion from neighbor-frame pixel deltas, smoothed over a short window. +- Lighting fluctuation from luminance deltas, smoothed over a short window. +- Face score from MediaPipe face detection, with OpenCV Haar cascades as a no-download fallback. + +The first and last 8% of frames are lightly penalized for normal-length videos, because endpoints are often less representative. + +## Install + +Clone into `ComfyUI/custom_nodes` and restart ComfyUI: + +```bash +git clone https://github.com/Pmobilee/ComfyUI-vid2frames.git ComfyUI-vid2frames +pip install -r ComfyUI-vid2frames/requirements.txt +``` + +## Tests + +```bash +python -m pytest tests/test_frame_selector.py -q +``` diff --git a/__init__.py b/__init__.py index f88e8bd..86f4d27 100644 --- a/__init__.py +++ b/__init__.py @@ -1,3 +1,15 @@ -from .frame_selector import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS +try: + from .frame_selector import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS +except ImportError: + import importlib.util + from pathlib import Path + + path = Path(__file__).resolve().parent / "frame_selector.py" + spec = importlib.util.spec_from_file_location("aia_frame_selector", path) + frame_selector = importlib.util.module_from_spec(spec) + spec.loader.exec_module(frame_selector) + + NODE_CLASS_MAPPINGS = frame_selector.NODE_CLASS_MAPPINGS + NODE_DISPLAY_NAME_MAPPINGS = frame_selector.NODE_DISPLAY_NAME_MAPPINGS __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]