v1 task queue: add TASK 19-23 (transitions, hotkeys, media source, audio sync, studio mode)
- TASKS.md: added 5 new tasks for v1 feature completeness, execution order, updated backlog - MONETIZATION.md: added v1 feature completeness section (competitive gap analysis) - ai.md: added v1 task queue note in Current limitations/TODOs - HANDOFF.md: updated session state and next steps - ViewModels/SocialsDialogViewModel.cs: removed isPremium parameter (social slot locks) - ViewModels/MainViewModel.cs: removed isPremium argument from SocialsDialogViewModel constructor - ytLive.Tests/SocialsDialogViewModelTests.cs: updated 5 tests for unlocked slots
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
# ytLlive — AI Guide
|
||||
|
||||
> Memory map entry point. Conventions live in [`schema.md`](schema.md); task
|
||||
> status and YouTube API research in [`TASKS.md`](TASKS.md); directory maps in
|
||||
> each folder's `index.md`. Reading order: this file → `TASKS.md` → `<dir>/index.md` → source.
|
||||
> status and YouTube API research in [`TASKS.md`](TASKS.md); brand/marketing
|
||||
> palette and launch strategy in [`MARCOM.md`](MARCOM.md) (gitignored — read
|
||||
> it before any branding or marketing work); directory maps in each folder's
|
||||
> `index.md`. Reading order: this file → `TASKS.md` → `MARCOM.md` → `<dir>/index.md` → source.
|
||||
|
||||
## Response style
|
||||
|
||||
@@ -25,6 +27,20 @@ of reassurance. In that mode:
|
||||
This is an occasional, explicitly-invoked mode — **never the default**. The
|
||||
default response style above stays in effect unless invoked.
|
||||
|
||||
## Brand
|
||||
|
||||
Brand palette and official assets live in `MARCOM.md` (gitignored — read it for hex values,
|
||||
asset file names, and marketing copy). The brand red `#e94560` is the primary accent used
|
||||
throughout the UI.
|
||||
|
||||
### AI transparency
|
||||
|
||||
This project is built through AI-assisted pair-programming. All code is generated
|
||||
under the supervision of an experienced developer with decades of coding experience.
|
||||
Architecture decisions, product direction, and quality gates are human-owned;
|
||||
AI accelerates implementation. This is a testimonial to successful human-AI
|
||||
collaboration, not autonomous code generation.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
@@ -113,9 +129,16 @@ C# / WPF (.NET 8) following MVVM:
|
||||
|
||||
- `Helpers/OAuthCredentials.cs` contains the real ClientId/ClientSecret. Auth is complete and the session **persists via Windows DPAPI** (`Helpers/TokenStore.cs` → `%APPDATA%\ytLlive\ytLlive.auth`, CurrentUser scope), reloaded best-effort at startup with a proactive refresh of a near-expiry access token. Sign-in/Change Account lives **inside the Start Stream dialog** (two-state flow — no separate Connect button). A **graceful End Livestream signs out**: `StopStream()` clears the session + token, so the next go-live needs a fresh sign-in; a crash never runs End, so the token survives and the creator stays signed in. `YouTubeAuthService` takes an optional `HttpClient` + `sessionChanged` callback (test seam + save hook; services are still constructed in `MainViewModel`)
|
||||
- Scene/source/asset layout + the social bar persist (SQLite, schema v8); the OAuth session persists (DPAPI); the paid-unlock state does not (yet — subscription entitlement verification pending, TASK 10)
|
||||
- `YouTubeStreamService` manages the **variable reusable stream** (shipped 2026-08-16): `GetOrCreateReusableStreamAsync` lists `liveStreams?mine=true` and reuses the existing `cdn.isReusable` stream, creating it only on first use (`resolution=variable`, `frameRate=variable`); the stream is cached via `LayoutStore` (`SaveReusableStream`/`LoadReusableStream`, Settings table) and bound at broadcast insert (`contentDetails.boundStreamId`). Health (shipped 2026-08-16): `GetStreamHealthAsync(streamId)` polls `liveStreams?part=status` for `healthStatus` + `configurationIssues[]` → `StreamHealth`; banner decision in pure `StreamHealthReporter`
|
||||
- `YouTubeStreamService` manages the **variable reusable stream** (shipped 2026-08-16): `GetOrCreateReusableStreamAsync` lists `liveStreams?mine=true` and reuses the existing `cdn.isReusable` stream, creating it only on first use (`resolution=variable`, `frameRate=variable`); the stream is cached via `LayoutStore` (`SaveReusableStream`/`LoadReusableStream`, Settings table) and bound at broadcast insert (`boundStreamId`). Health (shipped 2026-08-16): `GetStreamHealthAsync(streamId)` polls `liveStreams?part=status` for `healthStatus` + `configurationIssues[]` → `StreamHealth`; banner decision in pure `StreamHealthReporter`
|
||||
- Webcam capture is shipped (milestone 1); the live desktop/game backdrop is shipped (ship task #1); **the output compositor (TASK 4 ship step 1) is SHIPPED**, **the FFmpeg locator (TASK 4 ship step 2) is SHIPPED**, **the encoder + RTMP push (TASK 4 ship step 3) is SHIPPED**, **WASAPI audio capture (TASK 4 ship step 4) is SHIPPED** — full plan in `TASKS.md`; the frame-pipeline wiring follows (its own PR)
|
||||
- `StreamConfig` defaults (`TargetBitrate=6000`, `Resolution="1920x1080"`) are stale — the live dropdown drives `StreamHealth.CurrentBitrate`/`FPS` instead
|
||||
- **v1 task queue (2026-08-19):** 5 new tasks added for v1 feature completeness:
|
||||
- TASK 19: Scene transitions (Cut/Fade/Move/Custom) — required for professional polish
|
||||
- TASK 20: Hotkeys (global keyboard shortcuts) — the single biggest UX gap
|
||||
- TASK 21: Media source (video file playback) — starting soon videos, BRB loops
|
||||
- TASK 22: Audio sync offset — lip-sync correction for USB mics/capture cards
|
||||
- TASK 23: Studio mode (lightweight preview) — preview next scene before live
|
||||
- These were identified through competitive analysis and are table-stakes for any streaming software in 2025-2026. Full details in `TASKS.md`.
|
||||
|
||||
### Screen backdrop capture (TASK 3 ship task #1)
|
||||
|
||||
@@ -589,38 +612,41 @@ Apply this to every UI decision:
|
||||
|
||||
## Monetization (design decision — the branding flash is the sword)
|
||||
|
||||
Free forever: all streams unlimited, no time caps, no per-feature paywalls. The **one paid line is an
|
||||
annual subscription** (settled 2026-08-14 — replaces the earlier "one-time unlock" shape):
|
||||
Full pricing, discount codes, and Polar product details in `MONETIZATION.md` (gitignored).
|
||||
Brand palette and assets in `MARCOM.md` (gitignored). This section covers the in-app model.
|
||||
|
||||
- **Free:** a periodic full-frame branding flash — "made with ytLlive!" rendered big and centered at
|
||||
~25% opacity for about one second (soft 250ms fade in/out), repeated every 300s, on the live output
|
||||
(and on v0.2 local recordings). Implemented as `BrandFlashLayer` in the preview compositor
|
||||
Free forever: **all features unlocked for everyone** — no feature lock between free and paid.
|
||||
The **only difference is watermarking**. This is deliberate: no creator will tolerate a watermark,
|
||||
and as a good-guy developer, we give them complete access to every feature so no one can call us
|
||||
crooked.
|
||||
|
||||
- **Free:** a periodic full-frame branding flash — "made with LlamaCasty!" rendered big and centered
|
||||
at ~25% opacity for about one second (soft 250ms fade in/out), repeated every 300s, on the live
|
||||
output (and on local recordings). Implemented as `BrandFlashLayer` in the preview compositor
|
||||
(`MainWindow.xaml` CanvasGrid) + `BrandFlashTimer` in `MainViewModel` — cadence 300s, first flash
|
||||
~5s after go-live, only while live or recording. An always-on watermark can be cropped or covered;
|
||||
an intermittent full-frame flash can't be cropped and is impractical to edit around on a live feed.
|
||||
**The flash is also the free tier's billboard** — every free stream advertises ytLlive to its own
|
||||
viewers; the free tier is distribution, not compromise.
|
||||
- **Paid (annual subscription):** branding flash removed (flips `BrandFlashEnabled` off) + **Alerts**
|
||||
(Super Chat / membership / subscribe pop-ins). Alerts is the recurring-value engine — a live-API
|
||||
feature we maintain forever, which is the strongest argument for a yearly bill.
|
||||
**The flash is also the free tier's billboard** — every free stream advertises LlamaCasty to its
|
||||
own viewers; the free tier is distribution, not compromise.
|
||||
- **Paid (annual subscription):** branding flash removed (flips `BrandFlashEnabled` off). That's it.
|
||||
No feature gating. Alerts, social bar slots, voice filters, TRAX, recording — everything is free.
|
||||
- **Pricing:** early-access founders rate **$49.99/yr** → **$99/yr list at GA** (v1). **Grandfathering:
|
||||
early adopters keep $49.99/yr for as long as the subscription is maintained**; a lapse means renewal
|
||||
at list. That's the whole policy — no escalation matrix (a realistic product lifetime is a few years;
|
||||
keep the promise simple).
|
||||
- **Billing:** NOT locked to itch.io (creator's call 2026-08-14). Hunted fact — **itch.io has no native
|
||||
subscription billing** (no annual/recurring product billing; only pay-what-you-want, pre-orders,
|
||||
early-access, keys, and a Patreon integration). **Chosen platform: Polar (polar.sh)** — open-source
|
||||
MoR (Apache 2.0), handles payments, subscriptions, license keys, and global tax compliance.
|
||||
Startup Program gives Scale plan free for 12 months. Details in `MONETIZATION.md`.
|
||||
- **Billing:** **Polar (polar.sh)** — open-source MoR (Apache 2.0), handles payments, subscriptions,
|
||||
license keys, and global tax compliance. Startup Program gives Scale plan free for 12 months.
|
||||
Product: `d105dfa1-497e-423b-8cd4-e0ee2e3abbc0`. Checkout: `llamacasty.com` → Polar hosted page.
|
||||
Discounts: `LLAMAFOUNDER` (100% off, 50 uses), `LLAMA50` (50% off, 12 months). Details in `MONETIZATION.md`.
|
||||
- **Support (creator's model):** in-app bug-reporting mechanism → issues into git; most queries are
|
||||
how-tos / feature requests / manual-skimmers. Maintenance cadence = "when I get around to it" with
|
||||
emergency patches; not a 24/7 service promise.
|
||||
|
||||
Deliberately rejected: always-on watermark (obscurable — replaced by the flash), hard stream-time
|
||||
**What was rejected:** always-on watermark (obscurable — replaced by the flash), hard stream-time
|
||||
cutoffs (the worst dead end — a stream dying mid-broadcast reads as broken, and YouTube streams
|
||||
routinely run 2-4 hours), soft-limit nagging, freemium tiers, and donation-only (relies on the
|
||||
kindness of strangers). Resolution/quality ceilings are **deferred** — that decision belongs to the
|
||||
resolution & streaming-constraints conversation, not monetization.
|
||||
routinely run 2-4 hours), soft-limit nagging, freemium feature tiers, and donation-only (relies on
|
||||
the kindness of strangers). Resolution/quality ceilings are **deferred** — that decision belongs to
|
||||
the resolution & streaming-constraints conversation, not monetization.
|
||||
|
||||
## Auth gates Go Live, but not exploration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user