From f9d9e8c5fbddc33fcd15542c8b92ca87f7a44217 Mon Sep 17 00:00:00 2001 From: gilesb Date: Mon, 12 Jan 2026 06:52:07 +0000 Subject: [PATCH] Convert effects to new single-file format - dog: Convert to whole-video API with PEP 723 metadata - identity: Add as frame-by-frame effect Both now use @-tag docstrings for AI-readable metadata. Co-Authored-By: Claude Opus 4.5 --- dog/effect.py | 31 ++++++++++++++++++++----------- identity/effect.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 identity/effect.py diff --git a/dog/effect.py b/dog/effect.py index ab08625..028a3ea 100644 --- a/dog/effect.py +++ b/dog/effect.py @@ -1,14 +1,27 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = ["requests"] +# /// """ -Dog effect - returns dog.mkv regardless of input. +@effect dog +@version 1.0.0 +@author @giles@artdag.rose-ash.com +@temporal true -This is a constant effect that fetches from an immutable URL. +@description +Returns dog.mkv regardless of input. This is a constant effect that +fetches from an immutable URL and verifies the content hash. +Demonstrates a whole-video effect that ignores its input. + +@example + (fx dog) """ import hashlib import logging import shutil from pathlib import Path -from typing import Any, Dict +from typing import Any, Dict, List import requests @@ -28,12 +41,13 @@ def file_hash(path: Path) -> str: return hasher.hexdigest() -def effect_dog(input_path: Path, output_path: Path, config: Dict[str, Any]) -> Path: +def process(input_paths: List[Path], output_path: Path, params: Dict[str, Any], ctx) -> Path: """ - Dog effect - ignores input, returns dog.mkv. + Whole-video API: ignores input, returns dog.mkv. Downloads from immutable URL and verifies hash. """ + output_path = Path(output_path) output_path.parent.mkdir(parents=True, exist_ok=True) # Output with correct extension @@ -74,11 +88,6 @@ def effect_dog(input_path: Path, output_path: Path, config: Dict[str, Any]) -> P # Copy to output shutil.copy2(cached_file, actual_output) - logger.debug(f"EFFECT dog: {input_path.name} -> {actual_output} (input ignored)") + logger.debug(f"EFFECT dog: -> {actual_output} (input ignored)") return actual_output - - -# Export for registration -effect = effect_dog -name = "dog" diff --git a/identity/effect.py b/identity/effect.py new file mode 100644 index 0000000..c1a6449 --- /dev/null +++ b/identity/effect.py @@ -0,0 +1,35 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [] +# /// +""" +@effect identity +@version 1.0.0 +@author @giles@artdag.rose-ash.com +@temporal false + +@description +Identity effect - returns input unchanged. This is the foundational +effect where identity(x) = x. Uses frame-by-frame API but simply +passes frames through unmodified. + +@example + (fx identity) +""" + +import numpy as np + + +def process_frame(frame: np.ndarray, params: dict, state) -> tuple: + """ + Identity: return frame unchanged. + + Args: + frame: RGB frame as numpy array (H, W, 3) + params: Unused + state: Passed through unchanged + + Returns: + (frame, state) - both unchanged + """ + return frame, state