# ================================================================= # # == NEXUS TRADING RECORDER - INSTALLER (v23.8) == # # == (Fix: No Cut-off + 3s Buffer + Auto-Close Numbers) == # # ================================================================= # try { $Definition = '[DllImport("user32.dll")] public static extern bool SetProcessDPIAware();' Add-Type -MemberDefinition $Definition -Name "Win32DpiAware_Inst" -Namespace "NexusInst" -ErrorAction SilentlyContinue [NexusInst.Win32DpiAware_Inst]::SetProcessDPIAware() | Out-Null } catch {} Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing Write-Host "Initializing Nexus Recorder Setup v23.8..." -ForegroundColor Cyan $userDocs = [Environment]::GetFolderPath('MyDocuments') $userVideos = [Environment]::GetFolderPath('MyVideos') $nt8Folder = Join-Path -Path $userDocs "NinjaTrader 8" $ffmpegExe = Join-Path -Path $nt8Folder "ffmpeg\bin\ffmpeg.exe" $ffmpegDir = Join-Path -Path $nt8Folder "ffmpeg" $scriptDest = Join-Path -Path $nt8Folder "FFmpeg_Trigger_v5.ps1" if (-not (Test-Path $nt8Folder)) { New-Item -ItemType Directory -Path $nt8Folder -Force | Out-Null } if (-not (Test-Path $ffmpegExe)) { Write-Host "`n[System Check] FFmpeg not found. Downloading..." -ForegroundColor Yellow if (Test-Path $ffmpegDir) { Remove-Item $ffmpegDir -Recurse -Force -ErrorAction SilentlyContinue } $zipPath = "$env:TEMP\ffmpeg_installer.zip" Invoke-WebRequest -Uri "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip" -OutFile $zipPath Expand-Archive -Path $zipPath -DestinationPath "$env:TEMP\ff_temp" -Force $inner = Get-ChildItem "$env:TEMP\ff_temp\ffmpeg-*" | Select-Object -First 1 Move-Item -Path $inner.FullName -Destination $ffmpegDir Remove-Item $zipPath, "$env:TEMP\ff_temp" -Recurse -Force -ErrorAction SilentlyContinue Write-Host "FFmpeg Installed." -ForegroundColor Green } Write-Host "`nStep 1: Select where to save recordings" -ForegroundColor Yellow $folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog $selectedPath = if ($folderBrowser.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { $folderBrowser.SelectedPath } else { $userVideos } $finalSavePath = Join-Path $selectedPath "Trade Recordings" $audioDevices = @() $ffmpegOutput = & $ffmpegExe -list_devices true -f dshow -i dummy 2>&1 foreach ($line in ($ffmpegOutput -split [Environment]::NewLine)) { if ($line -match '(?<=\] ")(.*?)(?=" \(audio\))') { $audioDevices += $matches[0] } } $selectedMic = "" if ($audioDevices.Count -gt 0) { Write-Host "`nStep 2: Select Microphone" -ForegroundColor Yellow for ($i = 0; $i -lt $audioDevices.Count; $i++) { Write-Host "[$($i + 1)] $($audioDevices[$i])" } $mChoice = Read-Host "Select (0 for none)" if ($mChoice -as [int] -and $mChoice -gt 0) { $selectedMic = $audioDevices[$mChoice - 1] } } $screens = [System.Windows.Forms.Screen]::AllScreens Write-Host "`nStep 3: FLASHING MONITOR NUMBERS..." -ForegroundColor Yellow $idForms = New-Object System.Collections.Generic.List[System.Windows.Forms.Form] for ($i = 0; $i -lt $screens.Count; $i++) { $s = $screens[$i] $form = New-Object System.Windows.Forms.Form -Property @{ BackColor="Black"; FormBorderStyle="None"; TopMost=$true; StartPosition="Manual"; Bounds=$s.Bounds; Opacity=0.8 } $label = New-Object System.Windows.Forms.Label -Property @{ Text="$($i + 1)"; ForeColor="White"; Font=New-Object System.Drawing.Font("Arial Black", 300); Dock="Fill"; TextAlign="MiddleCenter" } $form.Controls.Add($label); $form.Show(); $form.Refresh(); [System.Windows.Forms.Application]::DoEvents(); $idForms.Add($form) } Start-Sleep -Seconds 3.5 foreach ($f in $idForms) { $f.Close() } $sChoice = Read-Host "`nEnter the number you saw on the screen you want to record" $selectedMonitorIndex = if ($sChoice -as [int] -and $sChoice -le $screens.Count) { $sChoice - 1 } else { 0 } $template = @' # --- CONFIG --- $ffmpegPath = "[[FFMPEG_PATH]]" $baseOutputFolder = "[[OUTPUT_PATH]]" $triggerFilePath = "[[TRIGGER_PATH]]" $micName = "[[MIC_NAME]]" $monitorIndex = [[MONITOR_INDEX]] Add-Type -AssemblyName System.Windows.Forms $targetScreen = [System.Windows.Forms.Screen]::AllScreens[$monitorIndex] $monitorWidth = [Math]::Floor($targetScreen.Bounds.Width / 2) * 2 $monitorHeight = [Math]::Floor($targetScreen.Bounds.Height / 2) * 2 $monitorOffsetX = $targetScreen.Bounds.X $monitorOffsetY = $targetScreen.Bounds.Y $lastSignal = "" $ffmpegProcess = $null Write-Host "==========================================================" -ForegroundColor Gray Write-Host " NEXUS RECORDER ACTIVE (v23.8 Pro-End)" -ForegroundColor Green Write-Host " Saving to: $baseOutputFolder" -ForegroundColor Cyan Write-Host "==========================================================" -ForegroundColor Gray while ($true) { if (-not (Get-Process "NinjaTrader" -ErrorAction SilentlyContinue)) { if ($ffmpegProcess) { Stop-Process -Id $ffmpegProcess.Id -Force -ErrorAction SilentlyContinue } exit } if (Test-Path $triggerFilePath) { try { $content = [System.IO.File]::ReadAllText($triggerFilePath).Trim() $currentSignal = if ($content) { $content } else { "" } if ($currentSignal -ne $lastSignal) { $time = Get-Date -Format "HH:mm:ss" if ($currentSignal -eq "EXIT") { if ($ffmpegProcess) { Stop-Process -Id $ffmpegProcess.Id -Force -ErrorAction SilentlyContinue } exit } if ($currentSignal -eq "START" -and $ffmpegProcess -eq $null) { Write-Host "[$time] STARTING RECORDING..." -ForegroundColor Cyan $year = Get-Date -Format "yyyy"; $month = Get-Date -Format "MMMM"; $day = Get-Date -Format "dd" $fullSavePath = Join-Path (Join-Path (Join-Path $baseOutputFolder $year) $month) $day if (-not (Test-Path $fullSavePath)) { New-Item -ItemType Directory -Path $fullSavePath -Force | Out-Null } $outputFilePath = Join-Path $fullSavePath "Trade_$(Get-Date -Format 'HH-mm-ss').mkv" # ENHANCED ARGS: -fflags nobuffer + -flush_packets ensures data is written to disk immediately $args = "-f gdigrab -draw_mouse 0 -framerate 30 -fflags nobuffer -offset_x $monitorOffsetX -offset_y $monitorOffsetY -video_size $($monitorWidth)x$($monitorHeight) -i desktop" if ($micName) { $args += " -f dshow -i `"audio=$micName`" -c:a aac -b:a 128k" } $args += " -c:v libx264 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -flush_packets 1 -y `"$outputFilePath`"" $ffmpegProcess = Start-Process -FilePath $ffmpegPath -ArgumentList $args -PassThru -NoNewWindow if ($ffmpegProcess) { Write-Host "[$time] Recording Active." -ForegroundColor Green } $lastSignal = "START" } elseif ($currentSignal -eq "STOP" -and $ffmpegProcess -ne $null) { Write-Host "[$time] STOPPING (Waiting 3s for final frames)..." -ForegroundColor Yellow # Wait 3 full seconds so NinjaTrader can draw the final trade result on chart Start-Sleep -Seconds 3 Stop-Process -Id $ffmpegProcess.Id -Force -ErrorAction SilentlyContinue $ffmpegProcess = $null;$lastSignal = "STOP"; Write-Host "DONE." -ForegroundColor Green } } } catch { } } Start-Sleep -Milliseconds 500 } '@ $finalScript = $template.Replace('[[FFMPEG_PATH]]', $ffmpegExe).Replace('[[OUTPUT_PATH]]', $finalSavePath).Replace('[[TRIGGER_PATH]]', (Join-Path $nt8Folder "NexusObsTrigger.log")).Replace('[[MIC_NAME]]', $selectedMic).Replace('[[MONITOR_INDEX]]', $selectedMonitorIndex) $finalScript | Set-Content -Path $scriptDest -Force Write-Host "`nSUCCESS! Optimized MKV Recording Script Created: $scriptDest" -ForegroundColor Green