feat(capture): lock decision #1 and prove Xvfb+Chromium frame capture
Decision #1: watch the real Discord screen share by running a real web client under a virtual display (Xvfb) and capturing rendered frames — not bot/selfbot protocol receive. PLAN.md records all locked decisions and the step list. PoC (poc/capture_xvfb.py + test_page.html) launches system Chrome non-headless under Xvfb via Playwright and captures 6 changing, non-blank frames -> de-risks the display+capture chain on the .9 host.
This commit is contained in:
29
poc/test_page.html
Normal file
29
poc/test_page.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"><title>capture test</title>
|
||||
<style>html,body{margin:0;background:#101418}</style></head>
|
||||
<body>
|
||||
<canvas id="c" width="1280" height="720"></canvas>
|
||||
<script>
|
||||
// An always-changing scene, so captured frames must differ frame-to-frame and
|
||||
// be non-blank. This stands in for "a Discord screen share is playing".
|
||||
const c = document.getElementById('c'), x = c.getContext('2d');
|
||||
let t = 0;
|
||||
function draw() {
|
||||
t++;
|
||||
x.fillStyle = '#101418'; x.fillRect(0, 0, 1280, 720);
|
||||
// moving box
|
||||
const px = (t * 7) % 1180;
|
||||
x.fillStyle = `hsl(${(t*3)%360} 80% 55%)`;
|
||||
x.fillRect(px, 300 + 120 * Math.sin(t / 15), 100, 100);
|
||||
// big live counter text
|
||||
x.fillStyle = '#e8eef2'; x.font = 'bold 90px monospace';
|
||||
x.fillText('FRAME ' + t, 60, 140);
|
||||
x.font = '28px monospace';
|
||||
x.fillText(new Date().toISOString(), 60, 200);
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
draw();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user