# LlamaCasty (repo `ytLive`) — AI guide & router > Read [`AGENTS.md`](AGENTS.md) first: the rules and the invariants. This file is the **map** — > what the product is, how it is built, and where each subsystem's truth lives. It carries no > narrative and no status. ## What it is A Windows-only WPF (.NET 8) app that live-streams to YouTube. Five fixed scenes (Starting / Live / BRB / Chat / Ending), a pure C# software compositor over an always-1920×1080 master, a bundled-ffmpeg encoder pushing RTMP, and a WASAPI audio chain. Freemium — the whole app is free at 30 fps across supported resolutions; Pro unlocks 60 fps — under a proprietary EULA, with no account creation: it links an existing YouTube channel. One-click go-live is the product; OBS is the escape hatch for anything bigger. ## Build, run, test Windows `dotnet.exe` from WSL; takes are read in **Release**. Full detail in [`docs/ai/environment.md`](docs/ai/environment.md). ```bash "/mnt/c/Program Files/dotnet/dotnet.exe" build "C:\Users\gramp\Documents\Code\projects\ytLive\ytLive.csproj" "/mnt/c/Program Files/dotnet/dotnet.exe" run -c Release "/mnt/c/Program Files/dotnet/dotnet.exe" vstest "C:\Users\gramp\Documents\Code\projects\ytLive\ytLive.Tests\bin\Debug\net8.0-windows10.0.19041.0\ytLive.Tests.dll" ``` `./scripts/verify.sh ""` is the one pre-commit gate (doc budgets, clean build at 0 warnings, tests, scope). ## Architecture C# / WPF (.NET 8) following MVVM: | Path | Role | |------|------| | `Models/` | Plain data types — Scene, Source (incl. `ClipShape`, `IsMirrored`, `VideoImageSource`), QualityOption, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage, **Socials (`SocialService` enum + `SocialEntry`/`SocialsConfig` + `SocialServiceIcons`) — the social bar** | | `ViewModels/` | MainViewModel — `public partial class`, one file per functional area (Scenes, Background, Webcam, Audio, Trax, Socials, Streaming, Chat, Overlays, Account, License, Recording — split complete, see `ViewModels/index.md`); **Chat.cs is a thin delegating facade over `Services/ChatOverlayLayer.cs` (Commit G, first true decomposition), and now also over `Services/AlertOverlayLayer.cs` (TASK 43 — the native alert box, same true-component pattern)**; GoLiveViewModel, ReuseImageViewModel, CameraPickerViewModel, **SocialsDialogViewModel** | | `Services/` | YouTube OAuth2, stream/broadcast management, live chat polling, LayoutStore (SQLite), **SocialValidator (`ISocialValidator` seam + `HttpSocialValidator` default)**, **webcam: `VideoFrame` seam + `CameraDeviceInfo`/`ICameraEnumerator`/`ICameraFrameSource` interfaces + `MediaCaptureCameraEnumerator`/`MediaCaptureFrameSource` (WinRT) + `CameraManager`**, **screen capture: `IFullScreenDetector`/`Win32FullScreenDetector` + `IScreenCaptureSource`/`ScreenCaptureFrameSource` (WinRT GraphicsCapture) + `ScreenCaptureManager` + `ScreenCaptureSourceFactory` + `Direct3D11Helper`/`CaptureInterop` (COM bridges)**, **media source: `IMediaFrameSource` + `MediaVideoSource` (spawns ffmpeg `rawvideo` BGRA decode) + `MediaVideoSourceManager` (refcount-by-path session owner) + pure `RawVideoFrameReader` + `IDecodeProcess`/`FfmpegDecodeProcess` process seam (binary-stdout mirror of `IEncoderProcess`; see [`TASKS/task-21-media-source.md`](TASKS/task-21-media-source.md))**, **compositor: `SceneCompositor` + `CompositorOptions` + pure `StretchMath` + `StaticPixelCache` (see [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) → "Scene compositor")**, **alerts: `ChatOverlayLayer` + `AlertOverlayLayer`/`AlertRenderer` (the native celebration-zone overlay, TASK 43 — see [`docs/ai/overlays.md`](docs/ai/overlays.md))**, **audio: `IAudioSource` seam + `WasapiLoopbackAudioSource`/`WasapiMicAudioSource` (NAudio WASAPI) + `AudioMixer` + pure `AudioLevelMeter`/`WaveToFloat`/`VoiceFilterChain`/`LowShelfFilter`/`HighShelfFilter`/`NoiseGate`/`Compressor`/`AutoDucker`/`AudioRingBuffer`/`TinyResampler`/`AudioSyncDelay` + `MusicPlayer` + `ITraxPlayer` (TRAX toggle seam — FakePlayer in tests; the dot is green/red/gray and the error scrolls terse in the desktop-audio bar; MusicVolume fixed 0.5) + `IAudioPipeWriter`/`NamedPipeAudioWriter` (see [`docs/ai/output.md`](docs/ai/output.md) → "Live audio capture")**, **encoder: `IFfmpegEncoder`/`FfmpegEncoder` + `IEncoderProcess`/`FfmpegEncoderProcess` + `IFfmpegLocator`/`FfmpegLocator` + pure `FfmpegArgs`/`FfmpegProgressParser`/`FfmpegEncoderPicker` + the `FramePump` frame producer (see [`docs/ai/output.md`](docs/ai/output.md) → "Live encoder" + [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) → "Live frame pipeline")**, **notifications: `INotificationService` seam (`AppNotificationSeverity` Info/Success/Warning/Error) + `NotificationService` (Notification.Wpf toasts, see "Toast notifications")** | | `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, **TokenStore (DPAPI session persistence)**, **BuildStamp (wordmark release counter `#N` = `git rev-list --count HEAD`, so it moves once per COMMIT; per-build GUID/time are logged to startup.log)**, visibility converters | | `Themes/` | `Controls.xaml` — the single dark-theme source, merged once in `App.xaml` (see `Themes/index.md`) | | `MainWindow.xaml` | Dark theme; top bar + health banner; work area has a fixed 360px left column and preview column, top-left readouts/resolution and scene strip above preview, lower left panel + preview; bottom bar is an empty spacer | ## Where the truth lives | Subsystem | File | Read when | |---|---|---| | Capture: backdrop, webcam, background effects, vertical tier | [`docs/ai/capture.md`](docs/ai/capture.md) | touching any frame source, the Background row, camera acquisition, or the 9:16 geometry | | Compositor, render budget, frame pump | [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) | changing the render loop, per-frame cost, pacing, backpressure, or dropped/juddering frames | | ffmpeg, encoder, recording, audio chain | [`docs/ai/output.md`](docs/ai/output.md) | ffmpeg args, REC/ON-AIR, the audio mix, loudness or sync | | Social bar, alerts, chat overlays | [`docs/ai/overlays.md`](docs/ai/overlays.md) | anything drawn on top of the output | | Go-live, broadcasts, health, chat API | [`docs/ai/youtube-api.md`](docs/ai/youtube-api.md) | go-live, broadcast lifecycle, health polling, streaming close-out | | Control surface, theming, transitions | [`docs/ai/ui-surface.md`](docs/ai/ui-surface.md) | anything the creator looks at | | Brand, packaging, legal posture | [`docs/ai/product.md`](docs/ai/product.md) | branding, naming, packaging behaviour, legal obligations | | Prices, entitlement, channels, support | [`docs/ai/commercial.md`](docs/ai/commercial.md) | anything about money: pricing, licence keys, output cap, Steam/Steamworks, the monthly plan, costs | | Hosts, build commands, test map | [`docs/ai/environment.md`](docs/ai/environment.md) | building, running, adding a test | | Routes for every subsystem | [`docs/ai/index.md`](docs/ai/index.md) | you want the full table with a "read when" per file | Lookup, not reading: [`MyMistakes.md`](MyMistakes.md) (grep first on any "did this before?" wall) · [`TASKS.md`](TASKS.md) (the queue) · `TASKS/` (per-task detail and API research) · `/index.md` (per-directory map). ## Current state [`HANDOFF.md`](HANDOFF.md) — branch, what's in flight, the next action, live landmines. Do not restate it here.