UNPKG

puppeteer-stream

Version:

An Extension for Puppeteer to retrieve audio and/or video streams of a page

270 lines 22.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStream = exports.getExtensionPage = exports.launch = exports.wss = void 0; const puppeteer_core_1 = require("puppeteer-core"); const path = __importStar(require("path")); const stream_1 = require("stream"); const ws_1 = __importStar(require("ws")); const extensionId = "jjndjgheafjngoipoacpjgeicjeomjli"; let currentIndex = 0; let port; exports.wss = (async () => { for (let i = 55200; i <= 65535; i++) { const ws = new ws_1.WebSocketServer({ port: i }); const promise = await Promise.race([ new Promise((resolve) => { ws.on("error", (e) => { resolve(!e.message.includes("EADDRINUSE")); }); }), new Promise((resolve) => { ws.on("listening", () => { resolve(true); }); }), ]); if (promise) { port = i; return ws; } } })(); async function launch(arg1, opts) { var _a, _b; //if puppeteer library is not passed as first argument, then first argument is options // @ts-ignore if (typeof arg1.launch != "function") opts = arg1; if (!opts) opts = {}; if (!opts.args) opts.args = []; function addToArgs(arg, value) { if (!value) { if (opts.args.includes(arg)) return; return opts.args.push(arg); } let found = false; opts.args = opts.args.map((x) => { if (x.includes(arg)) { found = true; return x + "," + value; } return x; }); if (!found) opts.args.push(arg + value); } if (!Array.isArray(opts.enableExtensions)) opts.enableExtensions = []; opts.enableExtensions.push(path.join(__dirname, "..", "extension")); opts.pipe = true; addToArgs("--autoplay-policy=no-user-gesture-required"); addToArgs("--auto-accept-this-tab-capture"); addToArgs(`--allowlisted-extension-id=${extensionId}`); if (((_a = opts.defaultViewport) === null || _a === void 0 ? void 0 : _a.width) && ((_b = opts.defaultViewport) === null || _b === void 0 ? void 0 : _b.height)) { opts.args.push(`--window-size=${opts.defaultViewport.width},${opts.defaultViewport.height}`); opts.args.push(`--ozone-override-screen-size=${opts.defaultViewport.width},${opts.defaultViewport.height}`); } // @ts-ignore opts.headless = opts.headless === "new" ? "new" : false; if (opts.headless) { if (!opts.ignoreDefaultArgs) opts.ignoreDefaultArgs = []; if (Array.isArray(opts.ignoreDefaultArgs) && !opts.ignoreDefaultArgs.includes("--mute-audio")) opts.ignoreDefaultArgs.push("--mute-audio"); if (!opts.args.includes("--headless=new")) opts.args.push("--headless=new"); } let browser; // @ts-ignore if (typeof arg1.launch == "function") { // @ts-ignore browser = await arg1.launch(opts); } else { browser = await (0, puppeteer_core_1.launch)(opts); } // Delay to let Chrome load the extension await new Promise((r) => setTimeout(r, opts.startDelay || 250)); if (opts.allowIncognito) { const settings = await browser.newPage(); await settings.goto(`chrome://extensions/?id=${extensionId}`); await settings.evaluate(() => { document .querySelector("extensions-manager") .shadowRoot.querySelector("#viewManager > extensions-detail-view.active") .shadowRoot.querySelector("div#container.page-container > div.page-content > div#options-section extensions-toggle-row#allow-incognito") .shadowRoot.querySelector("label#label input") .click(); }); await settings.close(); } (await browser.newPage()).goto(`chrome-extension://${extensionId}/options.html#${port}`); const old_browser_close = browser.close; browser.close = async () => { for (const page of await browser.pages()) { if (!page.url().startsWith(`chrome-extension://${extensionId}/options.html`)) { await page.close(); } } const extension = await getExtensionPage(browser); await extension.evaluate(async () => { return chrome.tabs.query({}); }); if (opts.closeDelay) { await new Promise((r) => setTimeout(r, opts.closeDelay)); } await old_browser_close.call(browser); }; return browser; } exports.launch = launch; async function getExtensionPage(browser) { const extensionTarget = await browser.waitForTarget((target) => { return target.type() === "page" && target.url().startsWith(`chrome-extension://${extensionId}/options.html`); }); if (!extensionTarget) throw new Error("cannot load extension"); const videoCaptureExtension = await extensionTarget.page(); if (!videoCaptureExtension) throw new Error("cannot get page of extension"); return videoCaptureExtension; } exports.getExtensionPage = getExtensionPage; let mutex = false; let queue = []; function lock() { return new Promise((res) => { if (!mutex) { mutex = true; return res(null); } queue.push(res); }); } function unlock() { if (queue.length) queue.shift()(); else mutex = false; } async function getStream(page, opts) { var _a; if (!opts.audio && !opts.video) throw new Error("At least audio or video must be true"); if (!opts.mimeType) { if (opts.video) opts.mimeType = "video/webm"; else if (opts.audio) opts.mimeType = "audio/webm"; } if (!opts.frameSize) opts.frameSize = 20; const retryPolicy = Object.assign({}, { each: 20, times: 3 }, opts.retry); const extension = await getExtensionPage(page.browser()); const highWaterMarkMB = ((_a = opts.streamConfig) === null || _a === void 0 ? void 0 : _a.highWaterMarkMB) || 8; const index = currentIndex++; await lock(); await page.bringToFront(); const [tab] = await extension.evaluate(async (x) => { // @ts-ignore return chrome.tabs.query(x); }, opts.tabQuery || { active: true, }); unlock(); if (!tab) throw new Error("Cannot find tab, try providing your own tabQuery to getStream options"); const stream = new stream_1.Transform({ highWaterMark: 1024 * 1024 * highWaterMarkMB, transform(chunk, encoding, callback) { callback(null, chunk); }, }); stream.stop = async () => { if (!extension.isClosed() && extension.browser().isConnected()) { // @ts-ignore await extension.evaluate((index) => STOP_RECORDING(index), index).catch(() => { }); } }; function onConnection(ws, req) { const url = new URL(`http://localhost:${port}${req.url}`); if (url.searchParams.get("index") != index.toString()) return; async function close() { if (!extension.isClosed() && extension.browser().isConnected()) { // @ts-ignore extension.evaluate((index) => STOP_RECORDING(index), index).catch(() => { }); } if (ws.readyState === ws_1.default.CLOSED) { if (!stream.destroyed && !stream.readableEnded && !stream.writableEnded) { stream.end(); } } (await exports.wss).off("connection", onConnection); } ws.on("message", (data) => { if (!stream.destroyed && !stream.writableEnded) { stream.write(data); } }); ws.on("close", close); page.on("close", close); stream.on("close", close); } (await exports.wss).on("connection", onConnection); await lock(); await page.bringToFront(); await assertExtensionLoaded(extension, retryPolicy); // Invoke extension via keyboard command to grant activeTab (Ctrl/Command+Shift+Y) const isMac = process.platform === 'darwin'; await page.keyboard.down(isMac ? 'Meta' : 'Control'); await page.keyboard.down('Shift'); await page.keyboard.press('KeyY'); await page.keyboard.up('Shift'); await page.keyboard.up(isMac ? 'Meta' : 'Control'); // Small delay to let Chrome register the invocation await new Promise((r) => setTimeout(r, 100)); await extension.evaluate( // @ts-ignore (settings) => START_RECORDING(settings), Object.assign(Object.assign({}, opts), { index, tabId: tab.id })); unlock(); return stream; } exports.getStream = getStream; async function assertExtensionLoaded(ext, opt) { const wait = (ms) => new Promise((res) => setTimeout(res, ms)); for (let currentTick = 0; currentTick < opt.times; currentTick++) { // @ts-ignore if (await ext.evaluate(() => typeof START_RECORDING === "function")) return; await wait(Math.pow(opt.each, currentTick)); } throw new Error("Could not find START_RECORDING function in the browser context"); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHVwcGV0ZWVyU3RyZWFtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1B1cHBldGVlclN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1EQUt3QjtBQUN4QiwyQ0FBNkI7QUFDN0IsbUNBQW1DO0FBQ25DLHlDQUFnRDtBQUdoRCxNQUFNLFdBQVcsR0FBRyxrQ0FBa0MsQ0FBQztBQUN2RCxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7QUFVckIsSUFBSSxJQUFZLENBQUM7QUFFSixRQUFBLEdBQUcsR0FBRyxDQUFDLEtBQUssSUFBSSxFQUFFO0lBQzlCLEtBQUssSUFBSSxDQUFDLEdBQUcsS0FBSyxFQUFFLENBQUMsSUFBSSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDcEMsTUFBTSxFQUFFLEdBQUcsSUFBSSxvQkFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ2xDLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ3ZCLEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBTSxFQUFFLEVBQUU7b0JBQ3pCLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0JBQzVDLENBQUMsQ0FBQyxDQUFDO1lBQ0osQ0FBQyxDQUFDO1lBQ0YsSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDdkIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFO29CQUN2QixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ2YsQ0FBQyxDQUFDLENBQUM7WUFDSixDQUFDLENBQUM7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLE9B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