$ cat node-template.py
Drive Video Reader
// Reads a video file from Drive and outputs it as a Video file.
Input
Storage
template.py
1import os2import sys3import json4import traceback5import requests67EMBLEMA_API_BASE_URL = os.getenv("EMBLEMA_API_BASE_URL")8USER_TOKEN = os.getenv("USER_TOKEN")9OUTPUT_DIR = "/data/output"1011if not EMBLEMA_API_BASE_URL:12 raise ValueError("EMBLEMA_API_BASE_URL environment variable not set")131415def api_request_json(method, path, **kwargs):16 """Make authenticated API request and return JSON response."""17 if not USER_TOKEN:18 raise ValueError("USER_TOKEN environment variable not set")1920 headers = {21 "Authorization": f"Bearer {USER_TOKEN}",22 }23 url = f"{EMBLEMA_API_BASE_URL}{path}"24 response = requests.request(method, url, headers=headers, **kwargs)25 response.raise_for_status()26 if not response.content:27 raise ValueError(f"API returned empty response body for {method} {path} (status {response.status_code})")28 try:29 return response.json()30 except json.JSONDecodeError:31 raise ValueError(32 f"API returned non-JSON response for {method} {path} "33 f"(status {response.status_code}, content-type: {response.headers.get('content-type', 'unknown')}, "34 f"body: {response.text[:200]})"35 )363738def fetch_video(drive_item_id_input) -> str:39 """Fetch a video file from Drive and save it to the output directory.4041 Args:42 drive_item_id_input: Single Drive Item ID (string). Arrays are rejected.4344 Returns:45 The output filename saved to /data/output/46 """47 # Normalize input — reject arrays, this is a single-video reader48 if isinstance(drive_item_id_input, list):49 if len(drive_item_id_input) == 1:50 drive_item_id = drive_item_id_input[0]51 else:52 raise ValueError(53 f"Drive Video Reader accepts a single video file, got {len(drive_item_id_input)} items. "54 "Use one Drive Video Reader per video file."55 )56 elif isinstance(drive_item_id_input, str):57 drive_item_id = drive_item_id_input58 else:59 raise ValueError(f"driveItemId must be a string, got {type(drive_item_id_input).__name__}")6061 if not drive_item_id:62 raise ValueError("No valid Drive Item ID provided")6364 # Get presigned download URL + metadata65 download_info = api_request_json("GET", f"/api/v2/drive/items/{drive_item_id}/download")6667 presigned_url = download_info.get("url")68 file_name = download_info.get("name", "video.mp4")69 mime_type = download_info.get("mimeType", "")7071 if not presigned_url:72 raise ValueError("Download API did not return a presigned URL")7374 # Validate that the file is a video file75 if mime_type and not mime_type.startswith("video/"):76 raise ValueError(77 f"Selected Drive item is not a video file (mimeType: {mime_type}). "78 "Please select a video file."79 )8081 # Download the video binary from presigned URL82 video_response = requests.get(presigned_url, timeout=120)83 video_response.raise_for_status()8485 # Save to output directory86 os.makedirs(OUTPUT_DIR, exist_ok=True)87 out_path = os.path.join(OUTPUT_DIR, file_name)88 with open(out_path, "wb") as f:89 f.write(video_response.content)9091 return file_name929394def main():95 """Main execution function"""96 try:97 input_json = sys.stdin.read().strip()98 if not input_json:99 raise ValueError("No input data received via stdin — executor did not pipe input correctly")100 execution_input = json.loads(input_json)101102 inputs = execution_input.get("inputs", {})103 drive_item_id = inputs.get("driveItemId")104105 if not drive_item_id:106 raise ValueError("Required input 'driveItemId' not provided")107108 filename = fetch_video(drive_item_id)109110 output = {111 "video": filename,112 }113114 print(json.dumps(output, indent=2))115116 except requests.HTTPError as e:117 error_output = {118 "error": f"API request failed: {e}",119 "errorType": "HTTPError",120 "status": e.response.status_code,121 "detail": e.response.text,122 }123 print(json.dumps(error_output), file=sys.stderr)124 sys.exit(1)125 except Exception as e:126 error_output = {127 "error": str(e),128 "errorType": type(e).__name__,129 "traceback": traceback.format_exc(),130 }131 print(json.dumps(error_output), file=sys.stderr)132 sys.exit(1)133134135if __name__ == "__main__":136 main()