diff --git a/docs/implementation-plan.md b/docs/implementation-plan.md index e145fc2..0690553 100644 --- a/docs/implementation-plan.md +++ b/docs/implementation-plan.md @@ -13,6 +13,8 @@ - Receiver OBS scene has `Neighbor PC - Video` and `Neighbor PC - Focusrite` Media Sources. - Voicemeeter loopback installed on the sender. - Receiver OBS scene has `Neighbor PC - System Audio` on SRT port `5102`. +- Sender script uses `-nostdin` and repo-root logs so desktop launchers stay alive and diagnostics land in `C:\Meta\LocalCastBridge\logs`. +- Sender video config currently matches the live `1024x768` desktop. ## Temporary @@ -23,8 +25,8 @@ ## Next -1. Open OBS and confirm the `Neighbor PC - Video` and `Neighbor PC - Focusrite` sources load. -2. Start the sender from Madman's desktop. +1. Open OBS and confirm the three `Neighbor PC` sources load. +2. Start the sender from Madman's interactive desktop, not SSH. 3. Smoke-test the video endpoint in OBS. 4. Smoke-test the Focusrite endpoint in OBS. 5. Smoke-test the system-loopback endpoint in OBS. diff --git a/docs/neighbor-sender-setup.md b/docs/neighbor-sender-setup.md index 350ce21..d38e2ed 100644 --- a/docs/neighbor-sender-setup.md +++ b/docs/neighbor-sender-setup.md @@ -37,6 +37,11 @@ focusrite srt://192.168.1.66:5101?mode=caller&latency=120000 system srt://192.168.1.66:5102?mode=caller&latency=120000 ``` +Current video capture size is `1024x768`, matching the live `WinDisc` display +reported by the sender. Do not force `1920x1080` unless Windows reports a real +desktop of that size; `gdigrab` exits when the requested capture rectangle is +larger than the current desktop. + OBS on the receiver should add listener-mode Media Sources: ```text @@ -75,6 +80,7 @@ Start launcher: - starts Voicemeeter - sets Windows default render to `Voicemeeter VAIO3 Input` - sets Windows default capture to `Voicemeeter Out B3` +- writes FFmpeg logs under `C:\Meta\LocalCastBridge\logs` Stop launcher: @@ -108,3 +114,18 @@ ffmpeg -hide_banner -f dshow -list_devices true -i dummy If Madman cannot hear local audio while LocalCast is running, open Voicemeeter and set hardware output `A1` to the intended physical device, probably Focusrite speakers/headphones. The stream capture itself is independent of OBS. + +## SSH Testing Trap + +Do not use an SSH-launched sender process as proof that video capture is broken. +When launched from SSH, `gdigrab` sees the remote Windows session desktop and +can fail with `Failed to capture image (error 5)`. The sender video process +must be launched from Madman's interactive desktop, normally through: + +```text +C:\Users\Madman's Lullaby\Desktop\Start LocalCast Sender.cmd +``` + +Attached SSH probes are still useful for audio devices and SRT reachability. +For example, an attached FFmpeg probe successfully transmitted audio to OBS on +ports `5101` and `5102`. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 2202e4b..b794863 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -27,12 +27,14 @@ Get-Content .\state\evidence.jsonl -Tail 8 - Madman's desktop has `Start LocalCast Sender.cmd` and `Stop LocalCast Sender.cmd`. - Receiver OBS scene collection has `Neighbor PC - Video`, `Neighbor PC - Focusrite`, and `Neighbor PC - System Audio` Media Sources added. - Sender has Voicemeeter plus SoundVolumeView installed for system-output loopback. +- Sender script was patched after failed transmission: live FFmpeg commands now include `-nostdin`, logs go under `C:\Meta\LocalCastBridge\logs`, and video capture size is `1024x768`. +- SSH-launched video capture fails with `gdigrab` error 5; test video from Madman's interactive desktop launcher. ## Current Pressure The useful next work is real hardware validation: -- open OBS and smoke-test the three configured receiver sources +- open OBS and smoke-test the three configured receiver sources from Madman's desktop launcher - tune latency once streams are live in OBS - add a real loopback/virtual audio capture source if system-output audio is required diff --git a/scripts/sender-start.ps1 b/scripts/sender-start.ps1 index 491c275..b2a3f28 100644 --- a/scripts/sender-start.ps1 +++ b/scripts/sender-start.ps1 @@ -5,6 +5,8 @@ param( ) $ErrorActionPreference = "Stop" +$Root = Split-Path -Parent (Split-Path -Parent $PSCommandPath) +$LogRoot = Join-Path $Root "logs" function Resolve-ConfigPath { param([string]$Path) @@ -54,6 +56,20 @@ function Format-CommandLine { return ($parts -join " ") } +function Format-ArgumentList { + param([string[]]$Arguments) + $parts = @() + foreach ($arg in $Arguments) { + if ($arg -match '[\s"&?=]') { + $escaped = $arg.Replace('"', '\"') + $parts += '"' + $escaped + '"' + } else { + $parts += $arg + } + } + return ($parts -join " ") +} + function Start-SourceProcess { param( [string]$Name, @@ -68,10 +84,11 @@ function Start-SourceProcess { return } - New-Item -ItemType Directory -Force ".\logs" | Out-Null - $stdout = Join-Path ".\logs" "$Name.out.log" - $stderr = Join-Path ".\logs" "$Name.err.log" - $process = Start-Process -FilePath $FfmpegPath -ArgumentList $Arguments -RedirectStandardOutput $stdout -RedirectStandardError $stderr -PassThru -WindowStyle Hidden + New-Item -ItemType Directory -Force $LogRoot | Out-Null + $stdout = Join-Path $LogRoot "$Name.out.log" + $stderr = Join-Path $LogRoot "$Name.err.log" + $argumentLine = Format-ArgumentList -Arguments $Arguments + $process = Start-Process -FilePath $FfmpegPath -ArgumentList $argumentLine -RedirectStandardOutput $stdout -RedirectStandardError $stderr -PassThru -WindowStyle Hidden Write-Host "$Name started. PID=$($process.Id) stdout=$stdout stderr=$stderr" } @@ -88,6 +105,7 @@ if ($settings.video -and $settings.video.enabled) { $videoUrl = Get-SrtUrl -Receiver $settings.receiver -PortOffset ([int]$settings.video.portOffset) $videoArgs = @( "-hide_banner", + "-nostdin", "-loglevel", "info", "-f", "gdigrab", "-framerate", "$($settings.video.framerate)", @@ -114,6 +132,7 @@ foreach ($audio in @($settings.audioSources)) { $audioUrl = Get-SrtUrl -Receiver $settings.receiver -PortOffset ([int]$audio.portOffset) $audioArgs = @( "-hide_banner", + "-nostdin", "-loglevel", "info", "-f", "dshow", "-i", "audio=$($audio.device)", diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 011d049..1f78b90 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -4,3 +4,4 @@ {"ts": "2026-05-18T10:24:49+00:00", "type": "deployment", "status": "ok", "note": "Neighbor sender 192.168.1.84 has LocalCastBridge under C:\\Meta\\LocalCastBridge, FFmpeg 8.1.1 with SRT/h264_nvenc, and desktop start/stop launchers targeting receiver 192.168.1.66 ports 5100/5101."} {"ts": "2026-05-18T10:27:41+00:00", "type": "deployment", "status": "ok", "note": "Receiver OBS Untitled scene now has Neighbor PC - Video and Neighbor PC - Focusrite ffmpeg_source Media Sources listening on SRT ports 5100 and 5101; original scene JSON was backed up before edit."} {"ts": "2026-05-18T10:52:05+00:00", "type": "deployment", "status": "ok", "note": "Installed Voicemeeter and SoundVolumeView on sender, added system-loopback using DirectShow device Voicemeeter Out B3 on SRT port 5102, and added matching OBS source Neighbor PC - System Audio."} +{"ts": "2026-05-18T11:38:25+00:00", "type": "fix", "status": "ok", "note": "Transmission failure traced to three issues: stale OBS SRT source state, sender live launcher splitting/closing FFmpeg due Start-Process/stdin handling, and SSH-launched gdigrab seeing a 1024x768 remote desktop with capture error 5. Patched sender-start with quoted argument string, -nostdin, repo-root logs, and set sender video config to 1024x768; OBS restarted and listening on UDP 5100-5102."} diff --git a/state/map.yaml b/state/map.yaml index 48d540b..999c3b3 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -49,7 +49,8 @@ current_status: First repo scaffold is in place and deployed to the neighbor sender at C:\Meta\LocalCastBridge. FFmpeg 8.1.1 with SRT and h264_nvenc is installed there, Voicemeeter supplies system-output loopback, Madman's desktop has - start/stop launchers, and the receiver OBS scene has matching Media Sources. + start/stop launchers, the sender script has launcher-safe FFmpeg arguments + and repo-root logs, and the receiver OBS scene has matching Media Sources. next_action: > - Open OBS, start the sender launcher from Madman's desktop, and smoke-test - video, Focusrite audio, and system audio. + With OBS open on the receiver, start the sender launcher from Madman's + interactive desktop and smoke-test video, Focusrite audio, and system audio.