$ cat node-template.py

V

Video Frame Interpolation

// Generates intermediate frames between existing frames. Output mode controls timing: 'smooth' increases frame rate at the same duration; 'slowmo' keeps the original frame rate and stretches the duration.

Process
Video
#video#interpolation#rife#frame-rate#slow-motion
template.py
1import os2import sys3import json4import traceback56from gais import Gais78INPUT_DIR = "/data/input"9OUTPUT_DIR = "/data/output"101112def main():13    try:14        input_json = sys.stdin.read()15        execution_input = json.loads(input_json)16        inputs = execution_input.get("inputs", {})1718        video = inputs.get("video", "")19        multiplier = int(inputs.get("multiplier", 2))20        output_mode = inputs.get("output_mode", "smooth")2122        if not video:23            raise ValueError("Video input is required")2425        video_path = os.path.join(INPUT_DIR, video)26        if not os.path.exists(video_path):27            raise FileNotFoundError(f"Input video not found: {video_path}")2829        os.makedirs(OUTPUT_DIR, exist_ok=True)3031        print(32            f"Interpolating: multiplier={multiplier}, output_mode={output_mode}",33            file=sys.stderr,34        )3536        result = Gais.video.interpolate(37            video=video_path,38            multiplier=multiplier,39            output_mode=output_mode,40        )4142        # Save output video43        base_name = os.path.splitext(os.path.basename(video))[0]44        out_filename = f"interpolated_{base_name}.mp4"45        out_path = os.path.join(OUTPUT_DIR, out_filename)46        with open(out_path, "wb") as f:47            f.write(result.content)4849        # Log metadata50        inference_ms = result.metadata.get("inference_time_ms", "unknown")51        print(52            f"Done: multiplier={multiplier}, output_mode={output_mode}, inference_time={inference_ms}ms",53            file=sys.stderr,54        )5556        # Probe output dimensions and emit aspect_ratio + resolution so57        # downstream nodes can chain.58        try:59            import av60            with av.open(out_path) as _c:61                _s = next(s for s in _c.streams if s.type == "video")62                _w = int(_s.codec_context.width)63                _h = int(_s.codec_context.height)64        except Exception:65            _w, _h = 0, 06667        # Flat output — keys match OUTPUT_SCHEMA68        output = {69            "video": out_filename,70            "aspect_ratio": round(_w / _h, 4) if _h else 0.0,71            "resolution": f"{_w}x{_h}",72        }73        print(json.dumps(output, indent=2))7475    except Exception as e:76        error_output = {77            "error": str(e),78            "errorType": type(e).__name__,79            "traceback": traceback.format_exc(),80        }81        print(json.dumps(error_output), file=sys.stderr)82        sys.exit(1)838485if __name__ == "__main__":86    main()

$ git log --oneline

v1.5.0
HEAD
2026-05-07
v1.3.02026-04-23
v1.0.02026-04-09