fix(web): wipe background-image too — the widget's black void is a CSS backdrop gradient, not a color
The 15:34 take's box interior is the widget's OWN full-canvas opaque paint — a
black void with wide content strips at the top/bottom and a right-edge bar —
arriving AFTER the first-second blank-transparent dumps. A background-color-only
!important wipe (b4bba4b) can't touch it because CSS gradients/backdrops are
background-IMAGE, not background-color.
OBS's fix for this exact symptom is background-image:none (obsproject/obs-studio#6659:
"set the CSS for html and body to background: none !important"). Injection now wipes
background-image:none!important on html,body,html * alongside the color wipe; HTML
overlay art (<img>/DOM/CSS shapes) survives — that is browser-source semantics.
Also re-arms WidgetDumpRemaining=5 ~30s after nav so the next take dumps the real
document INSIDE the recording window (the previous dumps proved blank at +1s and
missed the later backdrop paint).
9/9 WebView2Manager tests, 0 warnings.
This commit is contained in:
+20
-27
@@ -8,37 +8,30 @@ audio-silence are addressed).
|
||||
|
||||
## ACTIVE THREAD (ONE problem at a time)
|
||||
|
||||
**Web-uri transparency — branch (a) CONFIRMED and FIX-APPLIED, awaiting the verify take.**
|
||||
The 12:54/13:50 dumps proved the REAL widget document captures TRANSPARENT
|
||||
(`%TEMP%\ytLive-web-8d7234ec…-w1..5.png` alpha max 0/logged alpha 100% zero) YET the
|
||||
recording kept showing a black opaque box over the element rect (1231,679,705,396 — crisp
|
||||
edges, interior mean RGB ≈(1,6,13), NOT the desktop). Conclusion: the OLD inline
|
||||
`element.style.background='transparent'` injection only holds while the page has nothing
|
||||
to paint; once the widget connects and repaints a container background-COLOR, the capture
|
||||
re-opaques → black box. That is the OBS-solved class ("all web-uri resources paint their
|
||||
own background").
|
||||
**Web-uri transparency — second hardening applied (background-image wipe), awaiting take.**
|
||||
The 15:34 take: the recording's box interior is the widget's OWN full-canvas opaque paint
|
||||
(bright content strips at top/bottom + right bar over a black void) — NOT desktop, NOT a
|
||||
compositor blend. The real-document dumps showed blank-transparent at +1s and the page's
|
||||
backdrop appears later; a background-COLOR-only `!important` wipe (b4bba4b) leaves CSS
|
||||
background-IMAGE (gradient/backdrop) intact — the OBS answer is `background: none
|
||||
!important`, background-image too (obsproject/obs-studio#6659).
|
||||
|
||||
**Slice 14 change (commit target):** `WebView2Manager.TransparentBackgroundScript` is now a
|
||||
pre-parse `<style id='ytl-transparent-bg'>` wiping `background-color:transparent !important`
|
||||
on `html,body,html *` (background-images/art survive — only background-COLOR targeted).
|
||||
Idempotent by element id; `!important` outranks every page rule (OBS forums 2016 `body {
|
||||
background-color: rgba(0,0,0,0) !important }` + div variant, woahtech OBS custom-CSS guide —
|
||||
both cited in the commit message and `MyMistakes.md`).
|
||||
- `internal const` + regression test `TransparentBackgroundScript_Is_A_Important_Element_Wide_Wipe`
|
||||
(asserts element-wide `!important`, style-element form, and that the losing inline
|
||||
`.style.background=` form is gone).
|
||||
- Build 0 warnings; 9/9 WebView2Manager tests pass.
|
||||
**Slice 15 (commit target, the fix):**
|
||||
- `TransparentBackgroundScript` now also wipes `background-image:none!important` on
|
||||
`html,body,html *` (gradients/backdrops die; `<img>`/DOM art survives — OBS semantics).
|
||||
- `NavigateCompleted` re-arms `WidgetDumpRemaining = 5` ~30s in, so this take dumps the
|
||||
real document INSIDE the recording window (the missing evidence last time).
|
||||
- Test extended (asserts `background-image:none!important` present, weak inline form absent).
|
||||
|
||||
## THE ONE REMAINING STEP (verify, no further analysis)
|
||||
|
||||
1. User REPLACES the app (build is current) and records the Live scene, widget animating,
|
||||
like the 12:54/13:50 takes.
|
||||
2. Verdict: element rect shows scene bg with widget art over it (NO black box) → transparency
|
||||
C LOSED, push gate #1 clears. If it still shows a solid black box you can SEE at a glance
|
||||
inside the widget's 705×396 area, bring it + then (and ONLY then) audit what other layer
|
||||
paints that rect in the composite — the web capture has been exonerated twice.
|
||||
3. Then the queued layer-order-save bug (dragging an element over another doesn't persist
|
||||
`SortOrder`) is the next single use case.
|
||||
1. User records the Live scene, widget animating (pre-record ~35s so the 30s re-arm dump
|
||||
fires mid-take).
|
||||
2. Verdict: element rect shows the scene backdrop behind the widget art (no black box/void)
|
||||
→ transparency CLOSED, push gate #1 clears. If a black void persists BEYOND a visible
|
||||
background-image, it's not background painting and only chroma-key remains — bring the
|
||||
take and we do the compositor key, not more capture investigation.
|
||||
3. Then the queued layer-order-save bug (reorder doesn't persist `SortOrder`) is next.
|
||||
|
||||
## Other threads (paused)
|
||||
|
||||
|
||||
+16
-9
@@ -76,15 +76,22 @@ answer (valid for arbitrary pages for a decade) is an injected pre-parse `<style
|
||||
with `!important` beating every page rule:
|
||||
https://obsproject.com/forum/threads/translucent-transparent-browser-source.59549/
|
||||
(`body { background-color: rgba(0,0,0,0) !important }`) + the div-level variant for
|
||||
stubborn widgets (woahtech.com OBS custom-CSS guide). Applied 2026-09-10: the
|
||||
injection now appends a style element wiping `background-color:transparent!important`
|
||||
on `html,body,html *` (background-IMAGE and art survive). Self-inflicted again: the
|
||||
agent re-derived the whole transparency story (recording pixel archaeology,
|
||||
compositor blend re-verification) instead of reading this entry — the premise was
|
||||
already wrong once and the instrument said transparent, which it did because the
|
||||
capture had NOT been repainted yet. Verify take: if the 705×396 element rect shows
|
||||
the scene bg behind the widget art (animation visible, no black box) the loop closes.
|
||||
Do NOT re-derive this story a third time.
|
||||
stubborn widgets (woahtech.com OBS custom-CSS guide). Applied 2026-09-10 (b4bba4b):
|
||||
injection appends a style element wiping `background-color:transparent!important`
|
||||
on `html,body,html *`. **Second half (2026-09-10, 15:34 take): a background-COLOR wipe
|
||||
is NOT enough.** The 15:34 interior ASCII shows a black void with bright content strips
|
||||
at top/bottom + a right-edge bar — the widget's full-canvas CSS **background-image**
|
||||
(gradient/backdrop) painted after connect. The OBS fix for that is
|
||||
`background: none !important` / `background-image:none!important`
|
||||
(obsproject/obs-studio#6659 — "set the CSS for html and body to background: none
|
||||
!important"). Wipe both moving forward; overlay art is `<img>`/DOM and survives.
|
||||
Also the dumps only covered +1s (blank-transparent); the widget's backdrop paint
|
||||
arrives later, so the mid-recording dump set is now re-armed ~30s in. Verify take:
|
||||
element rect shows scene bg behind the widget art (animation, no black void) → loop
|
||||
closes. Self-inflicted again: the agent re-derived the whole transparency story
|
||||
(recording pixel archaeology, compositor blend re-verification) instead of reading
|
||||
this entry — the instrument said transparent because the capture had NOT been
|
||||
repainted yet. Do NOT re-derive this story a third time.
|
||||
|
||||
### Shrink / re-encode an image for the README (screenshots → small hero image)
|
||||
|
||||
|
||||
@@ -167,15 +167,22 @@ public sealed class WebView2Manager : IDisposable
|
||||
// and the div-level variant for stubborn widgets, woahtech.com OBS custom-CSS guide).
|
||||
// A `<style>` node injected before parse, with `!important`, outranks every page rule
|
||||
// (only an author !important beats a later document-order !important; ours runs first).
|
||||
// Only background-COLOR is wiped — background images and the widget art survive.
|
||||
// Only background-COLOR was wiped at first — the 15:34 take showed the widget's own
|
||||
// full-canvas backdrop surviving as the box's black void: that paint is a CSS
|
||||
// background-IMAGE (gradient/backdrop), and the OBS fix for the same symptom is
|
||||
// `background: none !important` / background-image none, not color alone
|
||||
// (obsproject/obs-studio#6659 — "set the CSS for html and body to background: none
|
||||
// !important"). Wipe background-image too; HTML overlay art (the widget's content) is
|
||||
// <img>/DOM/CSS shapes and survives — only container decorations are removed, which is
|
||||
// OBS-browser-source semantics for a transparent overlay.
|
||||
internal const string TransparentBackgroundScript =
|
||||
"(function(){" +
|
||||
"if(document.getElementById('ytl-transparent-bg'))return;" +
|
||||
"var s=document.createElement('style');" +
|
||||
"s.id='ytl-transparent-bg';" +
|
||||
"s.appendChild(document.createTextNode(" +
|
||||
"'html,body{background-color:transparent!important;margin:0!important;overflow:hidden!important;}'" +
|
||||
"'html,body,html *{background-color:transparent!important;}'" +
|
||||
"'html,body{background-color:transparent!important;background-image:none!important;margin:0!important;overflow:hidden!important;}'" +
|
||||
"'html,body,html *{background-color:transparent!important;background-image:none!important;}'" +
|
||||
"));" +
|
||||
"(document.head||document.documentElement).appendChild(s);" +
|
||||
"})();";
|
||||
@@ -210,6 +217,16 @@ public sealed class WebView2Manager : IDisposable
|
||||
// transparent margins the injection promises has never been
|
||||
// verified (MyMistakes: "? VERIFY").
|
||||
session.WidgetDumpRemaining = 5;
|
||||
// The first five dumps fire within ~1s of completion (usually BEFORE the
|
||||
// recording starts) — re-arm ~30s in so the same real document gets dumped
|
||||
// INSIDE a recording's window too. Next take therefore nukes the gap that
|
||||
// hid what the page actually painted while recording.
|
||||
var rearm = session;
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(30));
|
||||
rearm.WidgetDumpRemaining = 5;
|
||||
});
|
||||
}
|
||||
_ = CaptureFrame(source.Id);
|
||||
};
|
||||
|
||||
@@ -121,6 +121,7 @@ public sealed class WebView2ManagerTests
|
||||
var script = WebView2Manager.TransparentBackgroundScript;
|
||||
|
||||
Assert.Contains("background-color:transparent!important", script);
|
||||
Assert.Contains("background-image:none!important", script);
|
||||
Assert.Contains("html,body,html *", script);
|
||||
Assert.Contains("document.createElement('style')", script);
|
||||
Assert.DoesNotContain(".style.background=", script);
|
||||
|
||||
Reference in New Issue
Block a user