""" OBS Python Script for Automatic R2 Upload To use this script in OBS: 1. Open OBS Studio 2. Go to Tools → Scripts 3. Click the "+" button to add a script 4. Select this file (auto_upload.py) 5. Configure the settings in the script panel 6. Enable the script Requirements: - Python 3.8+ must be configured in OBS (Tools → Scripts → Python Settings) - obs_uploader package must be installed - .env file must be configured with R2 credentials """ import obspython as obs import os import sys import subprocess from pathlib import Path # Script settings enabled = True upload_script_path = "" project_root = "" show_notifications = True auto_delete = False def script_description(): """Return the description shown in OBS.""" return """

OBS R2 Auto-Upload

Automatically uploads completed recordings to Cloudflare R2.

Setup:

  1. Set the project root directory (where .env file is located)
  2. Ensure Python dependencies are installed
  3. Configure .env with R2 credentials
  4. Enable the script

When you stop recording, the video will be automatically uploaded.

""" def script_properties(): """Define script properties shown in OBS settings.""" props = obs.obs_properties_create() obs.obs_properties_add_bool( props, "enabled", "Enable Auto-Upload" ) obs.obs_properties_add_path( props, "project_root", "Project Root Directory", obs.OBS_PATH_DIRECTORY, "", "" ) obs.obs_properties_add_bool( props, "show_notifications", "Show Upload Notifications" ) obs.obs_properties_add_bool( props, "auto_delete", "Delete Local File After Upload" ) return props def script_defaults(settings): """Set default values for settings.""" obs.obs_data_set_default_bool(settings, "enabled", True) obs.obs_data_set_default_bool(settings, "show_notifications", True) obs.obs_data_set_default_bool(settings, "auto_delete", False) def script_update(settings): """Called when settings are updated.""" global enabled, project_root, show_notifications, auto_delete enabled = obs.obs_data_get_bool(settings, "enabled") project_root = obs.obs_data_get_string(settings, "project_root") show_notifications = obs.obs_data_get_bool(settings, "show_notifications") auto_delete = obs.obs_data_get_bool(settings, "auto_delete") print(f"[R2 Upload] Settings updated:") print(f" Enabled: {enabled}") print(f" Project Root: {project_root}") print(f" Notifications: {show_notifications}") print(f" Auto-delete: {auto_delete}") def script_load(settings): """Called when the script is loaded.""" print("[R2 Upload] Script loaded") # Connect to recording stopped signal obs.obs_frontend_add_event_callback(on_event) def script_unload(): """Called when the script is unloaded.""" print("[R2 Upload] Script unloaded") def on_event(event): """Handle OBS events.""" if not enabled: return # Recording stopped event if event == obs.OBS_FRONTEND_EVENT_RECORDING_STOPPED: print("[R2 Upload] Recording stopped, preparing upload...") # Get the last recording path recording_path = get_last_recording_path() if recording_path: print(f"[R2 Upload] Found recording: {recording_path}") upload_recording(recording_path) else: print("[R2 Upload] Could not determine recording path") def get_last_recording_path(): """Get the path of the last recording.""" # Get recording path from OBS output settings output = obs.obs_frontend_get_recording_output() if output: settings = obs.obs_output_get_settings(output) path = obs.obs_data_get_string(settings, "path") obs.obs_data_release(settings) obs.obs_output_release(output) if path and os.path.exists(path): return path # Alternative: Get from config config = obs.obs_frontend_get_profile_config() if config: # Try different possible config keys keys = [ "AdvOut.RecFilePath", "AdvOut.FFFilePath", "SimpleOutput.FilePath" ] for key in keys: path = obs.config_get_string(config, "Output", key) if path: # This gives us the directory, not the file # We'd need to find the most recent file if os.path.isdir(path): return get_most_recent_video(path) return None def get_most_recent_video(directory): """Get the most recently modified video file in a directory.""" video_extensions = ['.mp4', '.mkv', '.mov', '.avi', '.flv', '.wmv', '.webm'] video_files = [] for ext in video_extensions: video_files.extend(Path(directory).glob(f'*{ext}')) if not video_files: return None # Get most recent file most_recent = max(video_files, key=lambda p: p.stat().st_mtime) return str(most_recent) def upload_recording(file_path): """Upload a recording to R2.""" if not project_root: print("[R2 Upload] Error: Project root not configured") return if not os.path.exists(project_root): print(f"[R2 Upload] Error: Project root does not exist: {project_root}") return # Construct command upload_script = os.path.join(project_root, "obs_uploader", "upload.py") if not os.path.exists(upload_script): print(f"[R2 Upload] Error: Upload script not found: {upload_script}") return # Set environment variable for auto-delete env = os.environ.copy() if auto_delete: env["AUTO_DELETE_AFTER_UPLOAD"] = "true" # Build command cmd = [sys.executable, upload_script, file_path] print(f"[R2 Upload] Running: {' '.join(cmd)}") try: # Run upload in background result = subprocess.Popen( cmd, cwd=project_root, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # Don't wait for completion - it can take a while print(f"[R2 Upload] Upload started (PID: {result.pid})") if show_notifications: # Note: OBS doesn't have a built-in notification system # This just prints to the log print(f"[R2 Upload] Uploading {os.path.basename(file_path)} to R2...") except Exception as e: print(f"[R2 Upload] Error starting upload: {e}") # Note: For this script to work properly in OBS, you need to: # 1. Configure Python Settings in OBS to point to your Python installation # 2. Ensure the Python environment has access to the obs_uploader package # 3. Make sure .env file is properly configured # # Alternative approach: Use the file_watcher.py script instead, which runs # independently of OBS and is more reliable.