""" 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 """
Automatically uploads completed recordings to Cloudflare R2.
Setup:
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.