Private/Optimize-BsnCastIdleTime.ps1
|
<#
.SYNOPSIS Time-compresses idle periods in a cast file. .DESCRIPTION Implements the -RecordIdleTimeLimit semantics of RFC 421 (Terminal Session Recording): inter-event gaps longer than the limit are reduced to exactly the limit, so playback and video renders of long, idle-heavy sessions stay watchable. Event payloads are untouched; only the leading timestamp of each event line is rewritten. A limit of 0 (the cmdlet default) means unlimited and skips processing entirely. #> function Optimize-BsnCastIdleTime { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Path, [Parameter(Mandatory = $true)] [ValidateRange(1, [int]::MaxValue)] [int]$LimitSec ) $invariantCulture = [System.Globalization.CultureInfo]::InvariantCulture $timestampPattern = '^\[(\d+(?:\.\d+)?)' $header = ([System.IO.File]::ReadAllLines($Path) | Select-Object -First 1) | ConvertFrom-Json $isVersion3 = ($header.version -eq 3) if ($isVersion3) { # v3 files store intervals since the previous event: clamp each interval directly. $adjustedLines = [System.Collections.Generic.List[string]]::new() foreach ($castLine in [System.IO.File]::ReadAllLines($Path)) { if ($castLine -match $timestampPattern) { $interval = [double]::Parse($Matches[1], $invariantCulture) if ($interval -gt $LimitSec) { $interval = [double]$LimitSec } $adjustedLines.Add([regex]::Replace($castLine, '^\[\d+(?:\.\d+)?', ('[' + $interval.ToString('0.###', $invariantCulture)))) } else { $adjustedLines.Add($castLine) } } } else { # v2 files store absolute times: recompute each event against the previous event's new time. $adjustedLines = [System.Collections.Generic.List[string]]::new() $previousTime = $null foreach ($castLine in [System.IO.File]::ReadAllLines($Path)) { if ($castLine -match $timestampPattern) { $eventTime = [double]::Parse($Matches[1], $invariantCulture) if (($null -ne $previousTime) -and ((($eventTime - $previousTime) -gt $LimitSec))) { $eventTime = $previousTime + $LimitSec } $previousTime = $eventTime $adjustedLines.Add([regex]::Replace($castLine, '^\[\d+(?:\.\d+)?', ('[' + $eventTime.ToString('0.######', $invariantCulture)))) } else { $adjustedLines.Add($castLine) } } } $writer = [System.IO.StreamWriter]::new($Path, $false, [System.Text.UTF8Encoding]::new($false)) $writer.NewLine = "`n" try { foreach ($adjustedLine in $adjustedLines) { $writer.WriteLine($adjustedLine) } } finally { $writer.Dispose() } } |