$ cat node-template.py
Video Add Image Inside Canvas
// Overlays a static image onto a video at a specified position and size using ffmpeg.
Process
Video
template.py
1import os2import sys3import json4import subprocess5import traceback67INPUT_DIR = "/data/input"8OUTPUT_DIR = "/data/output"910FFMPEG_IMAGE = "jrottenberg/ffmpeg:7-ubuntu"11SVG_CONVERTER_IMAGE = "emblema/svg-converter:latest"121314def main():15 execution_input = json.loads(sys.stdin.read())16 inputs = execution_input.get("inputs", {})1718 x = inputs.get("x", 10)19 y = inputs.get("y", 10)20 z = inputs.get("z", 100)2122 os.makedirs(OUTPUT_DIR, exist_ok=True)2324 filter_complex = f"[1:v]scale={z}:-1[ovrl];[0:v][ovrl]overlay={x}:{y}"2526 # Use host staging paths (set by executor unconditionally)27 # so the sibling ffmpeg container mounts the same host directories.28 host_input = os.environ.get("HOST_STAGING_INPUT", INPUT_DIR)29 host_output = os.environ.get("HOST_STAGING_OUTPUT", OUTPUT_DIR)3031 image_file = inputs['image']32 image_input_path = f"/data/input/{image_file}"3334 if image_file.lower().endswith('.svg'):35 # Container 1: Convert SVG to transparent PNG via rsvg-convert36 svg_cmd = [37 "docker", "run", "--rm",38 "--network", "none",39 "--memory", "512m",40 "--cpus", "1.0",41 "-v", f"{host_input}:/data/input:ro",42 "-v", f"{host_output}:/data/output:rw",43 SVG_CONVERTER_IMAGE,44 "-w", str(z),45 "-a",46 f"/data/input/{image_file}",47 "-o", "/data/output/_overlay.png",48 ]49 result = subprocess.run(svg_cmd, capture_output=True, text=True)50 if result.returncode != 0:51 raise RuntimeError(f"rsvg-convert failed: {result.stderr}")52 image_input_path = "/data/output/_overlay.png"5354 video_path = f"/data/input/{inputs['video']}"55 shell_script = (56 "set -e\n"57 f"HAS_AUDIO=$(ffprobe -v quiet -select_streams a -show_entries stream=codec_type -of csv=p=0 '{video_path}' | head -1)\n"58 f"if [ -n \"$HAS_AUDIO\" ]; then\n"59 f" ffmpeg -y -i '{video_path}' -i '{image_input_path}' -filter_complex '{filter_complex}' -codec:a copy /data/output/output.mp4\n"60 f"else\n"61 f" ffmpeg -y -i '{video_path}' -i '{image_input_path}' -filter_complex '{filter_complex}' /data/output/output.mp4\n"62 f"fi\n"63 )6465 cmd = [66 "docker", "run", "--rm",67 "--network", "none",68 "--memory", "2g",69 "--cpus", "2.0",70 "-v", f"{host_input}:/data/input:ro",71 "-v", f"{host_output}:/data/output:rw",72 "--entrypoint", "sh",73 FFMPEG_IMAGE,74 "-c", shell_script,75 ]7677 result = subprocess.run(cmd, capture_output=True, text=True, timeout=1800)78 if result.returncode != 0:79 raise RuntimeError(f"ffmpeg failed (exit {result.returncode}): {result.stderr[-2000:]}")8081 print(json.dumps({"video": "output.mp4"}, indent=2))828384if __name__ == "__main__":85 try:86 main()87 except Exception as e:88 print(json.dumps({89 "error": str(e),90 "errorType": type(e).__name__,91 "traceback": traceback.format_exc(),92 }), file=sys.stderr)93 sys.exit(1)