#Requires -Version 5.1 <# .SYNOPSIS Launches OBS Studio hidden with the replay buffer running, then starts the tray icon. Intended to be called by DEM as a logon task (fire and forget — do not wait for completion). .NOTES Reads settings from config.psd1 one level above this script. Writes the OBS profile basic.ini dynamically so the correct UNC path and buffer duration are baked in at session start. #> $ErrorActionPreference = 'Stop' $configPath = Join-Path $PSScriptRoot '..\config.psd1' $config = Import-PowerShellDataFile -Path $configPath # --- Start transcript logging --- try { $logDir = [System.Environment]::ExpandEnvironmentVariables($config.LogPath) New-Item -ItemType Directory -Path $logDir -Force -ErrorAction SilentlyContinue | Out-Null Start-Transcript -Path (Join-Path $logDir 'OBSReplayBuffer.log') -Append -ErrorAction Stop } catch { # Log path unavailable — continue without transcript } Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Starting OBS Replay Buffer for user: $env:USERNAME" # --- Verify required project files are accessible --- $requiredPaths = @( (Join-Path $PSScriptRoot '..\obs-config\global.ini') (Join-Path $PSScriptRoot '..\obs-config\plugin_config\obs-websocket\config.json') (Join-Path $PSScriptRoot 'Show-ReplayTray.ps1') $config.OBSExecutable ) foreach ($path in $requiredPaths) { if (-not (Test-Path -Path $path)) { Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [ERROR] Required path not accessible: $path" Stop-Transcript -ErrorAction SilentlyContinue exit 1 } } Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] All required paths verified." # --- Skip if OBS is already running (handles reconnect scenarios) --- if (Get-Process -Name 'obs64' -ErrorAction SilentlyContinue) { Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS already running - exiting." Stop-Transcript -ErrorAction SilentlyContinue exit 0 } # --- Create user capture subfolder on UNC share --- $userCapturePath = Join-Path $config.UNCPath $env:USERNAME if (-not (Test-Path -Path $userCapturePath)) { New-Item -ItemType Directory -Path $userCapturePath -Force | Out-Null Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Created capture folder: $userCapturePath" } else { Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Capture folder exists: $userCapturePath" } # --- Detect primary monitor resolution --- Add-Type -AssemblyName System.Windows.Forms $screen = [System.Windows.Forms.Screen]::PrimaryScreen $width = $screen.Bounds.Width $height = $screen.Bounds.Height Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Detected resolution: ${width}x${height}" # --- Deploy global OBS config and WebSocket plugin config --- $obsConfigRoot = "$env:APPDATA\obs-studio" $sourceConfig = Join-Path $PSScriptRoot '..\obs-config' New-Item -ItemType Directory -Path $obsConfigRoot -Force | Out-Null Copy-Item -Path "$sourceConfig\global.ini" -Destination "$obsConfigRoot\global.ini" -Force $wsConfigDir = "$obsConfigRoot\plugin_config\obs-websocket" New-Item -ItemType Directory -Path $wsConfigDir -Force | Out-Null Copy-Item -Path "$sourceConfig\plugin_config\obs-websocket\config.json" -Destination "$wsConfigDir\config.json" -Force Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS config files deployed to: $obsConfigRoot" # --- Write OBS profile (basic.ini) --- $profileDir = "$env:APPDATA\obs-studio\basic\profiles\$($config.ProfileName)" New-Item -ItemType Directory -Path $profileDir -Force | Out-Null Set-Content -Path "$profileDir\basic.ini" -Encoding UTF8 -Value @( '[General]' "Name=$($config.ProfileName)" '' '[Output]' 'Mode=Simple' 'FilenameFormatting=%CCYY-%MM-%DD_%hh-%mm-%ss' '' '[SimpleOutput]' "FilePath=$userCapturePath" 'RecFormat2=mkv' 'RecQuality=HQ' "RecRBTime=$($config.BufferSeconds)" 'RecRBSize=512' '' '[Video]' "BaseCX=$width" "BaseCY=$height" "OutputCX=$width" "OutputCY=$height" 'FPSType=1' 'FPSNum=30' 'FPSDen=1' 'ScaleType=bicubic' 'ColorFormat=NV12' 'ColorSpace=709' 'ColorRange=Partial' ) Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS profile written: $profileDir\basic.ini" # --- Launch OBS hidden --- $obsArgs = @( '--minimize-to-tray' '--startreplaybuffer' '--disable-updater' '--profile' $config.ProfileName '--collection' $config.SceneCollection ) Start-Process -FilePath $config.OBSExecutable -ArgumentList $obsArgs -WindowStyle Hidden -WorkingDirectory (Split-Path $config.OBSExecutable) Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS launched: $($config.OBSExecutable)" # --- Launch tray icon as a separate background process --- $trayScript = Join-Path $PSScriptRoot 'Show-ReplayTray.ps1' Start-Process -FilePath 'powershell.exe' -ArgumentList @( '-ExecutionPolicy', 'Bypass' '-NonInteractive' '-WindowStyle', 'Hidden' '-File', $trayScript ) -WindowStyle Hidden Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Tray icon launched." Stop-Transcript -ErrorAction SilentlyContinue