feat(streamer): chromium cdp screencast driver
This commit is contained in:
parent
e0d93b03ae
commit
baef915561
1 changed files with 60 additions and 0 deletions
60
streamer/src/chrome.ts
Normal file
60
streamer/src/chrome.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { EventEmitter } from "node:events";
|
||||||
|
import puppeteer, { Browser, CDPSession, Page } from "puppeteer-core";
|
||||||
|
|
||||||
|
export interface ChromeOpts {
|
||||||
|
pageUrl: string;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
framerate: number;
|
||||||
|
jpegQuality?: number; // 0..100, default 85
|
||||||
|
executablePath?: string; // default /usr/bin/chromium
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChromeRenderer extends EventEmitter {
|
||||||
|
private browser: Browser | null = null;
|
||||||
|
private page: Page | null = null;
|
||||||
|
private cdp: CDPSession | null = null;
|
||||||
|
|
||||||
|
constructor(private opts: ChromeOpts) { super(); }
|
||||||
|
|
||||||
|
async start(): Promise<void> {
|
||||||
|
this.browser = await puppeteer.launch({
|
||||||
|
executablePath: this.opts.executablePath ?? "/usr/bin/chromium",
|
||||||
|
headless: true,
|
||||||
|
args: [
|
||||||
|
"--no-sandbox",
|
||||||
|
"--disable-dev-shm-usage",
|
||||||
|
"--disable-gpu",
|
||||||
|
"--hide-scrollbars",
|
||||||
|
`--window-size=${this.opts.width},${this.opts.height}`,
|
||||||
|
"--autoplay-policy=no-user-gesture-required",
|
||||||
|
],
|
||||||
|
defaultViewport: { width: this.opts.width, height: this.opts.height },
|
||||||
|
});
|
||||||
|
this.page = await this.browser.newPage();
|
||||||
|
await this.page.goto(this.opts.pageUrl, { waitUntil: "networkidle2" });
|
||||||
|
|
||||||
|
this.cdp = await this.page.target().createCDPSession();
|
||||||
|
await this.cdp.send("Page.startScreencast", {
|
||||||
|
format: "jpeg",
|
||||||
|
quality: this.opts.jpegQuality ?? 85,
|
||||||
|
everyNthFrame: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cdp.on("Page.screencastFrame", async (frame) => {
|
||||||
|
const buf = Buffer.from(frame.data, "base64");
|
||||||
|
this.emit("frame", buf);
|
||||||
|
await this.cdp!.send("Page.screencastFrameAck", { sessionId: frame.sessionId });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.browser.on("disconnected", () => this.emit("disconnected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
async stop(): Promise<void> {
|
||||||
|
try { await this.cdp?.send("Page.stopScreencast"); } catch { /* ignore */ }
|
||||||
|
await this.browser?.close().catch(() => {});
|
||||||
|
this.browser = null;
|
||||||
|
this.page = null;
|
||||||
|
this.cdp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue