$ cat node-template.py

V

Video Retake

// Regenerates a [start, end] time window of a video from a text prompt, preserving everything outside the window. Audio in the window is regenerated in sync (LTX 2.5).

Process
Video
template.py
1import os2import sys3import json4import traceback5import random67from gais import Gais89INPUT_DIR = "/data/input"10OUTPUT_DIR = "/data/output"111213def main():14    try:15        execution_input = json.loads(sys.stdin.read())16        inputs = execution_input.get("inputs", {})1718        prompt = inputs.get("prompt", "")19        if not prompt:20            raise ValueError("Prompt is required")2122        video_name = inputs.get("video", "")23        if not video_name:24            raise ValueError("A video is required")25        video_path = os.path.join(INPUT_DIR, video_name)26        if not os.path.exists(video_path):27            raise FileNotFoundError(f"Input video not found: {video_path}")2829        start_time = float(inputs.get("start_time", 0.0) or 0.0)30        end_time = float(inputs.get("end_time", 2.0) or 2.0)31        if start_time >= end_time:32            raise ValueError(33                f"Start ({start_time}s) must be before End ({end_time}s)"34            )3536        scope = (inputs.get("scope") or "audio+video").strip()37        regenerate_video = scope in ("audio+video", "video")38        regenerate_audio = scope in ("audio+video", "audio")3940        seed_mode = inputs.get("seed_mode", "random")41        seed_in = inputs.get("seed", -1)42        seed_input = int(seed_in) if seed_in not in (None, "") else -143        if seed_mode == "fixed" and seed_input >= 0:44            seed_value = seed_input45        else:46            seed_value = random.randint(0, 2**31 - 1)4748        os.makedirs(OUTPUT_DIR, exist_ok=True)49        print(50            f"Requesting video.retake: window=[{start_time}s, {end_time}s], "51            f"scope={scope}, seed={seed_value}",52            file=sys.stderr,53        )5455        result = Gais.video.retake(56            video=video_path,57            prompt=prompt,58            start_time=start_time,59            end_time=end_time,60            seed=seed_value,61            regenerate_video=regenerate_video,62            regenerate_audio=regenerate_audio,63        )6465        out_filename = "retake_video.mp4"66        out_path = os.path.join(OUTPUT_DIR, out_filename)67        with open(out_path, "wb") as f:68            f.write(result.content)6970        provider = result.metadata.get("provider_name", "local")71        print(f"retake generated via {provider}, seed={seed_value}", file=sys.stderr)7273        try:74            import av75            with av.open(out_path) as _c:76                _s = next(s for s in _c.streams if s.type == "video")77                _w = int(_s.codec_context.width)78                _h = int(_s.codec_context.height)79        except Exception:80            _w, _h = 0, 08182        print(json.dumps({83            "video": out_filename,84            "aspect_ratio": round(_w / _h, 4) if _h else 0.0,85            "resolution": f"{_w}x{_h}",86        }, indent=2))8788    except Exception as e:89        err = {90            "error": str(e),91            "errorType": type(e).__name__,92        }93        try:94            from gais._errors import GaisError95            is_backend_err = isinstance(e, GaisError)96        except Exception:97            is_backend_err = False98        if not is_backend_err:99            err["traceback"] = traceback.format_exc()100        print(json.dumps(err), file=sys.stderr)101        sys.exit(1)102103104if __name__ == "__main__":105    main()

$ git log --oneline

v1.0.0
HEAD
2026-08-18