47 lines
2.8 KiB
Markdown
47 lines
2.8 KiB
Markdown
# HANDOFF — session state
|
|
|
|
> Current operational state, read right after `TASKS.md`. Trust this file as the
|
|
> truth of what is in flight — do not re-derive from git/fs unless it points at
|
|
> a problem. Conventions: [`schema.md`](schema.md). Rewrite this file at session
|
|
> end, compaction, or any interruption.
|
|
|
|
## Session state (last updated: 2026-08-12)
|
|
|
|
- **Branch:** `main`. TASK 4 ship step 3 (encoder + RTMP push) is **built and
|
|
tested** but **NOT committed** — the working tree is dirty with the encoder
|
|
(10 new files in `Services/Encoder/` + `ytLive.Tests/FfmpegEncoderTests.cs`) and
|
|
its memory updates (TASKS.md, ai.md, Services/index.md). Ready to commit when
|
|
the user says so.
|
|
- **Finished this session:** TASK 4 ship step 3 — the FFmpeg subprocess encoder:
|
|
`EncoderOptions` + `IFfmpegEncoder`/`FfmpegEncoder` + `IEncoderProcess`/
|
|
`FfmpegEncoderProcess` + pure `FfmpegArgs`/`FfmpegProgressParser`/
|
|
`FfmpegEncoderPicker` in `Services/Encoder/`. StartAsync (locate → probe
|
|
`-encoders` → spawn → stderr loop), SubmitFrameAsync (serialized BGRA stdin),
|
|
StopAsync (stdin EOF → ffmpeg finalizes; 10s kill watchdog), ProcessFailed on
|
|
unexpected non-zero exit. Not yet constructed by the app (ship step 5 wiring).
|
|
Build: **0 warnings**. Tests: **122 passing** (was 112; +10 new).
|
|
- **Landmines:**
|
|
- `ChannelReader.ReadAsync` on a completed channel **throws**
|
|
`ChannelClosedException` — it does NOT return `null` like a StreamReader EOF.
|
|
The test fake (`QueuedReader` in `FfmpegEncoderTests.cs`) catches it and
|
|
returns `null`, or the encoder's stderr loop treats it as a fault and
|
|
`ProcessFailed` never fires (that's exactly what happened on the first run —
|
|
see commit history).
|
|
- The probe process (`FakeEncoderProcess`) must be a *separate* `IEncoderProcess`
|
|
instance from the encoder process in `Start_*` tests — `StartAsync` calls the
|
|
factory twice (probe → encoder), and the fake can't simulate both roles at
|
|
once.
|
|
- `StopAsync` waits the full `ExitTimeout` if the fake's process doesn't signal
|
|
exit — fakes must call `SignalExit()` inside `StopAsync`'s stdin-EOF path.
|
|
- Windows-only: `FfmpegEncoderProcess` sets `UseShellExecute=false` +
|
|
`RedirectStandardXxx=true` — never spawn with a shell.
|
|
- **Next step:** TASK 4 ship step 4 — WASAPI audio capture (loopback + mic)
|
|
feeding `AudioLevel` (req 7). Nothing else queued — do not expand the task
|
|
queue on your own.
|
|
|
|
- **Secret/DB/port facts live:** OAuth client id/secret in `Helpers/OAuthCredentials.cs`;
|
|
OAuth session token in `Helpers/TokenStore.cs` (DPAPI → `%APPDATA%\ytLlive\ytLlive.auth`);
|
|
layout DB `%APPDATA%\ytLlive\ytLlive.db` (schema v8; `SocialEntry.Software`
|
|
column is a column-presence migration like the others, no version bump); OAuth callback
|
|
`http://localhost:8765/oauth2/callback`; crash log `%APPDATA%\ytLlive\startup.log`.
|