Initial commit
This commit is contained in:
61
scripts/Invoke-ReplaySave.ps1
Normal file
61
scripts/Invoke-ReplaySave.ps1
Normal file
@@ -0,0 +1,61 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sends a SaveReplayBuffer request to OBS via WebSocket v5 (built into OBS 28+).
|
||||
Returns $true on success, $false on any failure.
|
||||
|
||||
.PARAMETER Port
|
||||
OBS WebSocket port. Defaults to the value in config.psd1.
|
||||
#>
|
||||
|
||||
param(
|
||||
[int]$Port = 0
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
|
||||
if ($Port -eq 0) {
|
||||
$config = Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..\config.psd1')
|
||||
$Port = $config.WebSocketPort
|
||||
}
|
||||
|
||||
$ws = $null
|
||||
$cts = $null
|
||||
|
||||
try {
|
||||
$ws = New-Object System.Net.WebSockets.ClientWebSocket
|
||||
$cts = New-Object System.Threading.CancellationTokenSource(5000) # 5-second timeout
|
||||
$uri = [System.Uri]"ws://localhost:$Port"
|
||||
|
||||
$ws.ConnectAsync($uri, $cts.Token).Wait()
|
||||
|
||||
$buffer = New-Object byte[] 8192
|
||||
|
||||
# Receive Hello (opcode 0)
|
||||
$null = $ws.ReceiveAsync($buffer, $cts.Token).Result
|
||||
|
||||
# Send Identify (opcode 1) — no authentication
|
||||
$identify = [System.Text.Encoding]::UTF8.GetBytes('{"op":1,"d":{"rpcVersion":1}}')
|
||||
$ws.SendAsync($identify, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token).Wait()
|
||||
|
||||
# Receive Identified (opcode 2)
|
||||
$null = $ws.ReceiveAsync($buffer, $cts.Token).Result
|
||||
|
||||
# Send SaveReplayBuffer request (opcode 6)
|
||||
$request = [System.Text.Encoding]::UTF8.GetBytes('{"op":6,"d":{"requestType":"SaveReplayBuffer","requestId":"itrecord-1"}}')
|
||||
$ws.SendAsync($request, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token).Wait()
|
||||
|
||||
# Receive RequestResponse (opcode 7)
|
||||
$null = $ws.ReceiveAsync($buffer, $cts.Token).Result
|
||||
|
||||
$ws.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, 'Done', $cts.Token).Wait()
|
||||
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
finally {
|
||||
if ($ws) { $ws.Dispose() }
|
||||
if ($cts) { $cts.Dispose() }
|
||||
}
|
||||
60
scripts/Show-ReplayTray.ps1
Normal file
60
scripts/Show-ReplayTray.ps1
Normal file
@@ -0,0 +1,60 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
System tray icon that lets users trigger an OBS replay buffer save.
|
||||
Right-click the tray icon to access Save Replay or Exit.
|
||||
|
||||
.NOTES
|
||||
This script blocks (runs a WinForms message loop) — launch it via Start-Process.
|
||||
Start-OBSReplayBuffer.ps1 handles launching this automatically at logon.
|
||||
#>
|
||||
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$saveScript = Join-Path $PSScriptRoot 'Invoke-ReplaySave.ps1'
|
||||
|
||||
# --- Tray icon ---
|
||||
$tray = New-Object System.Windows.Forms.NotifyIcon
|
||||
$tray.Icon = [System.Drawing.SystemIcons]::Shield
|
||||
$tray.Text = 'IT Screen Recorder'
|
||||
$tray.Visible = $true
|
||||
|
||||
# --- Context menu ---
|
||||
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
||||
$saveItem = New-Object System.Windows.Forms.ToolStripMenuItem('Save Replay')
|
||||
$sep = New-Object System.Windows.Forms.ToolStripSeparator
|
||||
$exitItem = New-Object System.Windows.Forms.ToolStripMenuItem('Exit')
|
||||
|
||||
$saveItem.Add_Click({
|
||||
$saveItem.Enabled = $false
|
||||
$saveItem.Text = 'Saving...'
|
||||
|
||||
$result = & powershell.exe -ExecutionPolicy Bypass -NonInteractive -File $saveScript
|
||||
|
||||
if ($result -eq $true) {
|
||||
$tray.ShowBalloonTip(4000, 'IT Screen Recorder', 'Replay saved.', [System.Windows.Forms.ToolTipIcon]::Info)
|
||||
}
|
||||
else {
|
||||
$tray.ShowBalloonTip(4000, 'IT Screen Recorder', 'Could not save replay. Please contact the helpdesk.', [System.Windows.Forms.ToolTipIcon]::Error)
|
||||
}
|
||||
|
||||
$saveItem.Text = 'Save Replay'
|
||||
$saveItem.Enabled = $true
|
||||
})
|
||||
|
||||
$exitItem.Add_Click({
|
||||
$tray.Visible = $false
|
||||
[System.Windows.Forms.Application]::Exit()
|
||||
})
|
||||
|
||||
$menu.Items.Add($saveItem) | Out-Null
|
||||
$menu.Items.Add($sep) | Out-Null
|
||||
$menu.Items.Add($exitItem) | Out-Null
|
||||
|
||||
$tray.ContextMenuStrip = $menu
|
||||
|
||||
# --- Message loop (blocks until Exit is chosen) ---
|
||||
[System.Windows.Forms.Application]::Run()
|
||||
|
||||
$tray.Dispose()
|
||||
86
scripts/Start-OBSReplayBuffer.ps1
Normal file
86
scripts/Start-OBSReplayBuffer.ps1
Normal file
@@ -0,0 +1,86 @@
|
||||
#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
|
||||
|
||||
# --- Skip if OBS is already running (handles reconnect scenarios) ---
|
||||
if (Get-Process -Name 'obs64' -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
|
||||
}
|
||||
|
||||
# --- 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 OBS profile (basic.ini) ---
|
||||
$profileDir = "$env:APPDATA\obs-studio\basic\profiles\$($config.ProfileName)"
|
||||
New-Item -ItemType Directory -Path $profileDir -Force | Out-Null
|
||||
|
||||
@"
|
||||
[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
|
||||
"@ | Set-Content -Path "$profileDir\basic.ini" -Encoding UTF8
|
||||
|
||||
# --- 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
|
||||
|
||||
# --- 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
|
||||
Reference in New Issue
Block a user