From f26fe839a2f8e13c3e97ee5f50b9942b8ce51abe Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Thu, 18 Feb 2021 18:22:23 +0100 Subject: [PATCH] do not patch puppeteer but, export functions --- README.md | 9 ++- dist/PuppeteerStream.d.ts | 6 +- dist/PuppeteerStream.js | 42 ++++------- dist/src/PuppeteerStream.d.ts | 25 +++++++ dist/src/PuppeteerStream.js | 136 ++++++++++++++++++++++++++++++++++ dist/tests/index.d.ts | 1 + dist/tests/index.js | 42 +++++++++++ examples/discord.js | 2 +- package-lock.json | 74 +++++++++--------- package.json | 4 +- src/PuppeteerStream.ts | 41 ++++------ tests/index.js | 36 +++++++++ tsconfig.json | 2 +- 13 files changed, 322 insertions(+), 98 deletions(-) create mode 100644 dist/src/PuppeteerStream.d.ts create mode 100644 dist/src/PuppeteerStream.js create mode 100644 dist/tests/index.d.ts create mode 100644 dist/tests/index.js create mode 100644 tests/index.js diff --git a/README.md b/README.md index 95ad6de..7c2ed83 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,12 @@ This will patch the launch method of puppeteer to start with this record extensi ### This will only work in headful mode -The method `page.getStream(options)` takes the following options: +The method `page.getStream(options)` takes the following options ```ts { - audio: boolean; // wheter or not to enable audio - video: boolean; // wheter or not to enable video + audio: boolean; // whether or not to enable audio + video: boolean; // whether or not to enable video mimeType?: string; // optional mime type of the stream, e.g. "audio/webm" or "video/webm" audioBitsPerSecond?: number; // The chosen bitrate for the audio component of the media. videoBitsPerSecond?: number; // The chosen bitrate for the video component of the media. @@ -44,9 +44,10 @@ The method `page.getStream(options)` takes the following options: frameSize?: number = 20; // The number of milliseconds to record into each packet. } ``` - and returns a `Promise<`[`Readable`](/dist/PuppeteerStream.d.ts#L4)`>` +For a detailed documentation of the options have a look at the [HTML5 MediaRecorder Options](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder) + ## Example ### [Save Stream to File:](/examples/example.js) diff --git a/dist/PuppeteerStream.d.ts b/dist/PuppeteerStream.d.ts index 703e714..b217800 100644 --- a/dist/PuppeteerStream.d.ts +++ b/dist/PuppeteerStream.d.ts @@ -1,5 +1,5 @@ /// -import { Page } from "puppeteer/lib/cjs/puppeteer/common/Page"; +import puppeteer, { LaunchOptions, Page, BrowserOptions, ChromeArgOptions } from "puppeteer"; import { Readable, ReadableOptions } from "stream"; export declare class Stream extends Readable { private page; @@ -13,7 +13,8 @@ declare module "puppeteer" { getStream(opts: getStreamOptions): Promise; } } -export declare type BrowserMimeType = "audio/webm" | "audio/webm;codecs=opus" | "audio/opus" | "audio/aac" | "audio/ogg" | "audio/mp3" | "audio/pcm" | "audio/wav" | "audio/vorbis" | "video/webm" | "video/mp4" | "image/gif"; +export declare function launch(opts: LaunchOptions & BrowserOptions & ChromeArgOptions): Promise; +export declare type BrowserMimeType = "audio/webm" | "audio/webm;codecs=opus" | "audio/opus" | "audio/aac" | "audio/ogg" | "audio/mp3" | "audio/pcm" | "audio/wav" | "audio/vorbis" | "video/webm" | "video/mp4"; export interface getStreamOptions { audio: boolean; video: boolean; @@ -23,3 +24,4 @@ export interface getStreamOptions { bitsPerSecond?: number; frameSize?: number; } +export declare function getStream(page: Page, opts: getStreamOptions): Promise; diff --git a/dist/PuppeteerStream.js b/dist/PuppeteerStream.js index 647bff8..ea6fd64 100644 --- a/dist/PuppeteerStream.js +++ b/dist/PuppeteerStream.js @@ -12,12 +12,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.Stream = void 0; +exports.getStream = exports.launch = exports.Stream = void 0; const puppeteer_1 = __importDefault(require("puppeteer")); -const Page_1 = require("puppeteer/lib/cjs/puppeteer/common/Page"); const stream_1 = require("stream"); const path_1 = __importDefault(require("path")); -const Browser_1 = require("puppeteer/lib/cjs/puppeteer/common/Browser"); class Stream extends stream_1.Readable { constructor(page, options) { super(options); @@ -34,9 +32,7 @@ class Stream extends stream_1.Readable { } } exports.Stream = Stream; -const oldLaunch = puppeteer_1.default.launch; -// @ts-ignore -puppeteer_1.default.launch = function (opts) { +function launch(opts) { var _a, _b, _c, _d; return __awaiter(this, void 0, void 0, function* () { if (!opts) @@ -72,10 +68,10 @@ puppeteer_1.default.launch = function (opts) { 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=${(_c = opts.defaultViewport) === null || _c === void 0 ? void 0 : _c.width}x${(_d = opts.defaultViewport) === null || _d === void 0 ? void 0 : _d.height}`); opts.headless = false; - const browser = yield oldLaunch.call(this, opts); + const browser = yield puppeteer_1.default.launch(opts); // @ts-ignore browser.encoders = new Map(); - const targets = yield browser.targets(); + const targets = browser.targets(); const extensionTarget = targets.find( // @ts-ignore (target) => target.type() === "background_page" && target._targetInfo.title === "Video Capture"); @@ -89,20 +85,11 @@ puppeteer_1.default.launch = function (opts) { }); return browser; }); -}; -const oldNewPage = Browser_1.Browser.prototype.newPage; -Browser_1.Browser.prototype.newPage = function () { - return __awaiter(this, void 0, void 0, function* () { - const page = yield oldNewPage.call(this); - const pages = yield this.pages(); - page.index = pages.length - 1; - return page; - }); -}; -// @ts-ignore -Page_1.Page.prototype.getStream = function (opts) { +} +exports.launch = launch; +function getStream(page, opts) { return __awaiter(this, void 0, void 0, function* () { - const encoder = new Stream(this); + const encoder = new Stream(page); if (!opts.audio && !opts.video) throw new Error("At least audio or video must be true"); if (!opts.mimeType) { @@ -113,17 +100,18 @@ Page_1.Page.prototype.getStream = function (opts) { } if (!opts.frameSize) opts.frameSize = 20; - yield this.bringToFront(); + yield page.bringToFront(); // @ts-ignore - yield this.browser().videoCaptureExtension.evaluate((settings) => { + yield page.browser().videoCaptureExtension.evaluate((settings) => { // @ts-ignore START_RECORDING(settings); - }, Object.assign(Object.assign({}, opts), { index: this.index })); + }, Object.assign(Object.assign({}, opts), { index: page._id })); // @ts-ignore - this.browser().encoders.set(this.index, encoder); + page.browser().encoders.set(page._id, encoder); return encoder; }); -}; +} +exports.getStream = getStream; function str2ab(str) { // Convert a UTF-8 String to an ArrayBuffer var buf = new ArrayBuffer(str.length); // 1 byte for each char @@ -133,4 +121,4 @@ function str2ab(str) { } return buf; } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHVwcGV0ZWVyU3RyZWFtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1B1cHBldGVlclN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQSwwREFBcUQ7QUFDckQsa0VBQStEO0FBQy9ELG1DQUFtRDtBQUNuRCxnREFBd0I7QUFDeEIsd0VBQXFFO0FBRXJFLE1BQWEsTUFBTyxTQUFRLGlCQUFRO0lBQ25DLFlBQW9CLElBQVUsRUFBRSxPQUF5QjtRQUN4RCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFESSxTQUFJLEdBQUosSUFBSSxDQUFNO0lBRTlCLENBQUM7SUFFRCxLQUFLLEtBQUksQ0FBQztJQUVWLE9BQU87UUFDTixLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDaEIsZ0RBQWdEO1FBQ2hELHNDQUFzQztRQUN0QyxrREFBa0Q7UUFDbEQsa0JBQWtCO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMxQixDQUFDO0NBQ0Q7QUFmRCx3QkFlQztBQVNELE1BQU0sU0FBUyxHQUFHLG1CQUFTLENBQUMsTUFBTSxDQUFDO0FBQ25DLGFBQWE7QUFDYixtQkFBUyxDQUFDLE1BQU0sR0FBRyxVQUFnQixJQUFtQjs7O1FBQ3JELElBQUksQ0FBQyxJQUFJO1lBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7WUFBRSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUUvQixNQUFNLGFBQWEsR0FBRyxjQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDOUQsTUFBTSxXQUFXLEdBQUcsa0NBQWtDLENBQUM7UUFDdkQsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1FBQ2hDLElBQUksV0FBVyxH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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHVwcGV0ZWVyU3RyZWFtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1B1cHBldGVlclN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQSwwREFBc0c7QUFDdEcsbUNBQW1EO0FBQ25ELGdEQUF3QjtBQUV4QixNQUFhLE1BQU8sU0FBUSxpQkFBUTtJQUNuQyxZQUFvQixJQUFVLEVBQUUsT0FBeUI7UUFDeEQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBREksU0FBSSxHQUFKLElBQUksQ0FBTTtJQUU5QixDQUFDO0lBRUQsS0FBSyxLQUFJLENBQUM7SUFFVixPQUFPO1FBQ04sS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2hCLGdEQUFnRDtRQUNoRCxzQ0FBc0M7UUFDdEMsa0RBQWtEO1FBQ2xELGtCQUFrQjtRQUNsQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDMUIsQ0FBQztDQUNEO0FBZkQsd0JBZUM7QUFTRCxTQUFzQixNQUFNLENBQUMsSUFBdUQ7OztRQUNuRixJQUFJLENBQUMsSUFBSTtZQUFFLElBQUksR0FBRyxFQUFFLENBQUM7UUFFckIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJO1lBQUUsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFFL0IsTUFBTSxhQUFhLEdBQUcsY0FBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzlELE1BQU0sV0FBVyxHQUFHLGtDQUFrQyxDQUFDO1FBQ3ZELElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMxQixJQUFJLG1CQUFtQixHQUFHLEtBQUssQ0FBQztRQUNoQyxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFFeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNuQixJQUFJLENBQUMsQ0FB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 \ No newline at end of file diff --git a/dist/src/PuppeteerStream.d.ts b/dist/src/PuppeteerStream.d.ts new file mode 100644 index 0000000..703e714 --- /dev/null +++ b/dist/src/PuppeteerStream.d.ts @@ -0,0 +1,25 @@ +/// +import { Page } from "puppeteer/lib/cjs/puppeteer/common/Page"; +import { Readable, ReadableOptions } from "stream"; +export declare class Stream extends Readable { + private page; + constructor(page: Page, options?: ReadableOptions); + _read(): void; + destroy(): Promise; +} +declare module "puppeteer" { + interface Page { + index: number; + getStream(opts: getStreamOptions): Promise; + } +} +export declare type BrowserMimeType = "audio/webm" | "audio/webm;codecs=opus" | "audio/opus" | "audio/aac" | "audio/ogg" | "audio/mp3" | "audio/pcm" | "audio/wav" | "audio/vorbis" | "video/webm" | "video/mp4" | "image/gif"; +export interface getStreamOptions { + audio: boolean; + video: boolean; + mimeType?: BrowserMimeType; + audioBitsPerSecond?: number; + videoBitsPerSecond?: number; + bitsPerSecond?: number; + frameSize?: number; +} diff --git a/dist/src/PuppeteerStream.js b/dist/src/PuppeteerStream.js new file mode 100644 index 0000000..ee29237 --- /dev/null +++ b/dist/src/PuppeteerStream.js @@ -0,0 +1,136 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Stream = void 0; +const puppeteer_1 = __importDefault(require("puppeteer")); +const Page_1 = require("puppeteer/lib/cjs/puppeteer/common/Page"); +const stream_1 = require("stream"); +const path_1 = __importDefault(require("path")); +const Browser_1 = require("puppeteer/lib/cjs/puppeteer/common/Browser"); +class Stream extends stream_1.Readable { + constructor(page, options) { + super(options); + this.page = page; + } + _read() { } + destroy() { + super.destroy(); + // TODO: do not destory page just stop recording + // await page.evaluate((filename) => { + // window.postMessage({ type: "REC_STOP" }, "*"); + // }, exportname); + return this.page.close(); + } +} +exports.Stream = Stream; +const oldLaunch = puppeteer_1.default.launch; +// @ts-ignore +puppeteer_1.default.launch = function (opts) { + var _a, _b, _c, _d; + return __awaiter(this, void 0, void 0, function* () { + if (!opts) + opts = {}; + if (!opts.args) + opts.args = []; + const extensionPath = path_1.default.join(__dirname, "..", "extension"); + const extensionId = "jjndjgheafjngoipoacpjgeicjeomjli"; + let loadExtension = false; + let loadExtensionExcept = false; + let whitelisted = false; + opts.args.map((x) => { + if (x.includes("--load-extension=")) { + loadExtension = true; + return x + "," + extensionPath; + } + else if (x.includes("--disable-extensions-except=")) { + loadExtensionExcept = true; + return x + "," + extensionPath; + } + else if (x.includes("--whitelisted-extension-id")) { + whitelisted = true; + return x + "," + extensionId; + } + return x; + }); + if (!loadExtension) + opts.args.push("--load-extension=" + extensionPath); + if (!loadExtensionExcept) + opts.args.push("--disable-extensions-except=" + extensionPath); + if (!whitelisted) + opts.args.push("--whitelisted-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=${(_c = opts.defaultViewport) === null || _c === void 0 ? void 0 : _c.width}x${(_d = opts.defaultViewport) === null || _d === void 0 ? void 0 : _d.height}`); + opts.headless = false; + const browser = yield oldLaunch.call(this, opts); + // @ts-ignore + browser.encoders = new Map(); + const targets = yield browser.targets(); + const extensionTarget = targets.find( + // @ts-ignore + (target) => target.type() === "background_page" && target._targetInfo.title === "Video Capture"); + // @ts-ignore + browser.videoCaptureExtension = yield extensionTarget.page(); + // @ts-ignore + yield browser.videoCaptureExtension.exposeFunction("sendData", (opts) => { + const data = Buffer.from(str2ab(opts.data)); + // @ts-ignore + browser.encoders.get(opts.id).push(data); + }); + return browser; + }); +}; +const oldNewPage = Browser_1.Browser.prototype.newPage; +Browser_1.Browser.prototype.newPage = function () { + return __awaiter(this, void 0, void 0, function* () { + const page = yield oldNewPage.call(this); + const pages = yield this.pages(); + page.index = pages.length - 1; + return page; + }); +}; +// @ts-ignore +Page_1.Page.prototype.getStream = function (opts) { + return __awaiter(this, void 0, void 0, function* () { + const encoder = new Stream(this); + 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; + yield this.bringToFront(); + // @ts-ignore + yield this.browser().videoCaptureExtension.evaluate((settings) => { + // @ts-ignore + START_RECORDING(settings); + }, Object.assign(Object.assign({}, opts), { index: this.index })); + // @ts-ignore + this.browser().encoders.set(this.index, encoder); + return encoder; + }); +}; +function str2ab(str) { + // Convert a UTF-8 String to an ArrayBuffer + var buf = new ArrayBuffer(str.length); // 1 byte for each char + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHVwcGV0ZWVyU3RyZWFtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL1B1cHBldGVlclN0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQSwwREFBcUQ7QUFDckQsa0VBQStEO0FBQy9ELG1DQUFtRDtBQUNuRCxnREFBd0I7QUFDeEIsd0VBQXFFO0FBRXJFLE1BQWEsTUFBTyxTQUFRLGlCQUFRO0lBQ25DLFlBQW9CLElBQVUsRUFBRSxPQUF5QjtRQUN4RCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFESSxTQUFJLEdBQUosSUFBSSxDQUFNO0lBRTlCLENBQUM7SUFFRCxLQUFLLEtBQUksQ0FBQztJQUVWLE9BQU87UUFDTixLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDaEIsZ0RBQWdEO1FBQ2hELHNDQUFzQztRQUN0QyxrREFBa0Q7UUFDbEQsa0JBQWtCO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMxQixDQUFDO0NBQ0Q7QUFmRCx3QkFlQztBQVNELE1BQU0sU0FBUyxHQUFHLG1CQUFTLENBQUMsTUFBTSxDQUFDO0FBQ25DLGFBQWE7QUFDYixtQkFBUyxDQUFDLE1BQU0sR0FBRyxVQUFnQixJQUFtQjs7O1FBQ3JELElBQUksQ0FBQyxJQUFJO1lBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7WUFBRSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUUvQixNQUFNLGFBQWEsR0FBRyxjQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDOUQsTUFBTSxXQUFXLEdBQUcsa0NBQWtDLENBQUM7UUFDdkQsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1FBQ2hDLElBQUksV0FB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 \ No newline at end of file diff --git a/dist/tests/index.d.ts b/dist/tests/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/tests/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/tests/index.js b/dist/tests/index.js new file mode 100644 index 0000000..25a5d1b --- /dev/null +++ b/dist/tests/index.js @@ -0,0 +1,42 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function videoRecorder() { + return __awaiter(this, void 0, void 0, function* () { + require("../dist/PuppeteerStream"); + const puppeteer = require("puppeteer"); + const fs = require("fs"); + const filename = `./test.mp4`; + const file = fs.createWriteStream(filename); + const browser = yield puppeteer.launch({ + executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + headless: true, + defaultViewport: null, + devtools: false, + args: ["--window-size=1920,1080", "--window-position=1921,0", "--autoplay-policy=no-user-gesture-required"], + ignoreDefaultArgs: ["--mute-audio"], + }); + const page = yield browser.newPage(); + yield page.goto("https://dl5.webmfiles.org/big-buck-bunny_trailer.webm", { + waitUntil: "load", + }); + const stream = yield page.getStream({ + audio: true, + video: true, + }); + stream.pipe(file); + setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield stream.destroy(); + file.close(); + console.log("finished"); + }), 10000); + }); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0cy9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsU0FBZSxhQUFhOztRQUMzQixPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUNuQyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkMsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXpCLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQztRQUU5QixNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQ3RDLGNBQWMsRUFBRSw4REFBOEQ7WUFDOUUsUUFBUSxFQUFFLElBQUk7WUFDZCxlQUFlLEVBQUUsSUFBSTtZQUNyQixRQUFRLEVBQUUsS0FBSztZQUNmLElBQUksRUFBRSxDQUFDLHlCQUF5QixFQUFFLDBCQUEwQixFQUFFLDRDQUE0QyxDQUFDO1lBQzNHLGlCQUFpQixFQUFFLENBQUMsY0FBYyxDQUFDO1NBQ25DLENBQUMsQ0FBQztRQUVILE1BQU0sSUFBSSxHQUFHLE1BQU0sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRXJDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyx1REFBdUQsRUFBRTtZQUN4RSxTQUFTLEVBQUUsTUFBTTtTQUNqQixDQUFDLENBQUM7UUFFSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDbkMsS0FBSyxFQUFFLElBQUk7WUFDWCxLQUFLLEVBQUUsSUFBSTtTQUNYLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbEIsVUFBVSxDQUFDLEdBQVMsRUFBRTtZQUNyQixNQUFNLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3pCLENBQUMsQ0FBQSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ1gsQ0FBQztDQUFBIn0= \ No newline at end of file diff --git a/examples/discord.js b/examples/discord.js index 1747fcf..b3d8602 100644 --- a/examples/discord.js +++ b/examples/discord.js @@ -1,4 +1,4 @@ -// npm i discord.js @discordjs/opus +// npm i discord.js @discordjs/opus ffmpeg-static puppeteer puppeteer-stream // start this script const { Client } = require("discord.js"); require("puppeteer-stream"); diff --git a/package-lock.json b/package-lock.json index da25b14..a1abacd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "version": "1.0.7", "license": "ISC", "dependencies": { - "puppeteer": "^5.5.0" + "puppeteer": "^7.1.0" }, "devDependencies": { "@types/node": "^14.14.14", @@ -40,9 +40,12 @@ } }, "node_modules/agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, "engines": { "node": ">= 6.0.0" } @@ -148,9 +151,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.818844", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", - "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==" + "version": "0.0.847576", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.847576.tgz", + "integrity": "sha512-0M8kobnSQE0Jmly7Mhbeq0W/PpZfnuK+WjN2ZRVPbGqYwCHCioAVp84H0TcLimgECcN5H976y5QiXMGBC9JKmg==" }, "node_modules/end-of-stream": { "version": "1.4.4", @@ -244,15 +247,15 @@ } }, "node_modules/https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dependencies": { - "agent-base": "5", + "agent-base": "6", "debug": "4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 6" } }, "node_modules/ieee754": { @@ -424,19 +427,19 @@ } }, "node_modules/puppeteer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz", - "integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-7.1.0.tgz", + "integrity": "sha512-lqOLzqCKdh7yUAHvK6LxgOpQrL8Bv1/jvS8MLDXxcNms2rlM3E8p/Wlwc7efbRZ0twxTzUeqjN5EqrTwxOwc9g==", "hasInstallScript": true, "dependencies": { "debug": "^4.1.0", - "devtools-protocol": "0.0.818844", + "devtools-protocol": "0.0.847576", "extract-zip": "^2.0.0", - "https-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.1", "pkg-dir": "^4.2.0", "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", + "proxy-from-env": "^1.1.0", "rimraf": "^3.0.2", "tar-fs": "^2.0.0", "unbzip2-stream": "^1.3.3", @@ -606,9 +609,12 @@ } }, "agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } }, "balanced-match": { "version": "1.0.0", @@ -672,9 +678,9 @@ } }, "devtools-protocol": { - "version": "0.0.818844", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", - "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==" + "version": "0.0.847576", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.847576.tgz", + "integrity": "sha512-0M8kobnSQE0Jmly7Mhbeq0W/PpZfnuK+WjN2ZRVPbGqYwCHCioAVp84H0TcLimgECcN5H976y5QiXMGBC9JKmg==" }, "end-of-stream": { "version": "1.4.4", @@ -744,11 +750,11 @@ } }, "https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "requires": { - "agent-base": "5", + "agent-base": "6", "debug": "4" } }, @@ -874,18 +880,18 @@ } }, "puppeteer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz", - "integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-7.1.0.tgz", + "integrity": "sha512-lqOLzqCKdh7yUAHvK6LxgOpQrL8Bv1/jvS8MLDXxcNms2rlM3E8p/Wlwc7efbRZ0twxTzUeqjN5EqrTwxOwc9g==", "requires": { "debug": "^4.1.0", - "devtools-protocol": "0.0.818844", + "devtools-protocol": "0.0.847576", "extract-zip": "^2.0.0", - "https-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.1", "pkg-dir": "^4.2.0", "progress": "^2.0.1", - "proxy-from-env": "^1.0.0", + "proxy-from-env": "^1.1.0", "rimraf": "^3.0.2", "tar-fs": "^2.0.0", "unbzip2-stream": "^1.3.3", diff --git a/package.json b/package.json index 4c1bec4..c190478 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "puppeteer-stream", - "version": "1.0.7", + "version": "2.0.0", "description": "", "main": "dist/PuppeteerStream.js", "types": "dist/PuppeteerStream.d.ts", @@ -19,7 +19,7 @@ }, "license": "ISC", "dependencies": { - "puppeteer": "^5.5.0" + "puppeteer": "^7.1.0" }, "devDependencies": { "@types/node": "^14.14.14", diff --git a/src/PuppeteerStream.ts b/src/PuppeteerStream.ts index 45b46c0..fd19a52 100644 --- a/src/PuppeteerStream.ts +++ b/src/PuppeteerStream.ts @@ -1,8 +1,6 @@ -import puppeteer, { LaunchOptions } from "puppeteer"; -import { Page } from "puppeteer/lib/cjs/puppeteer/common/Page"; +import puppeteer, { LaunchOptions, Browser, Page, BrowserOptions, ChromeArgOptions } from "puppeteer"; import { Readable, ReadableOptions } from "stream"; import path from "path"; -import { Browser } from "puppeteer/lib/cjs/puppeteer/common/Browser"; export class Stream extends Readable { constructor(private page: Page, options?: ReadableOptions) { @@ -28,10 +26,9 @@ declare module "puppeteer" { } } -const oldLaunch = puppeteer.launch; -// @ts-ignore -puppeteer.launch = async function (opts: LaunchOptions) { +export async function launch(opts: LaunchOptions & BrowserOptions & ChromeArgOptions) { if (!opts) opts = {}; + if (!opts.args) opts.args = []; const extensionPath = path.join(__dirname, "..", "extension"); @@ -63,11 +60,11 @@ puppeteer.launch = async function (opts: LaunchOptions) { opts.headless = false; - const browser: Browser = await oldLaunch.call(this, opts); + const browser: Browser = await puppeteer.launch(opts); // @ts-ignore browser.encoders = new Map(); - const targets = await browser.targets(); + const targets = browser.targets(); const extensionTarget = targets.find( // @ts-ignore (target) => target.type() === "background_page" && target._targetInfo.title === "Video Capture" @@ -83,15 +80,7 @@ puppeteer.launch = async function (opts: LaunchOptions) { }); return browser; -}; - -const oldNewPage = Browser.prototype.newPage; -Browser.prototype.newPage = async function (this: Browser) { - const page = await oldNewPage.call(this); - const pages = await this.pages(); - page.index = pages.length - 1; - return page; -}; +} export type BrowserMimeType = | "audio/webm" @@ -104,8 +93,7 @@ export type BrowserMimeType = | "audio/wav" | "audio/vorbis" | "video/webm" - | "video/mp4" - | "image/gif"; + | "video/mp4"; export interface getStreamOptions { audio: boolean; @@ -117,9 +105,8 @@ export interface getStreamOptions { frameSize?: number; } -// @ts-ignore -Page.prototype.getStream = async function (this: Page, opts: getStreamOptions) { - const encoder = new Stream(this); +export async function getStream(page: Page, opts: getStreamOptions) { + const encoder = new Stream(page); 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"; @@ -127,23 +114,23 @@ Page.prototype.getStream = async function (this: Page, opts: getStreamOptions) { } if (!opts.frameSize) opts.frameSize = 20; - await this.bringToFront(); + await page.bringToFront(); // @ts-ignore - await (this.browser().videoCaptureExtension).evaluate( + await (page.browser().videoCaptureExtension).evaluate( (settings) => { // @ts-ignore START_RECORDING(settings); }, // @ts-ignore - { ...opts, index: this.index } + { ...opts, index: page._id } ); // @ts-ignore - this.browser().encoders.set(this.index, encoder); + page.browser().encoders.set(page._id, encoder); return encoder; -}; +} function str2ab(str: any) { // Convert a UTF-8 String to an ArrayBuffer diff --git a/tests/index.js b/tests/index.js new file mode 100644 index 0000000..10050a9 --- /dev/null +++ b/tests/index.js @@ -0,0 +1,36 @@ +async function videoRecorder() { + const { getStream, launch } = require("../dist/PuppeteerStream"); + const fs = require("fs"); + + const filename = `./test.webm`; + + const file = fs.createWriteStream(filename); + + const browser = await launch({ + executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + headless: true, + defaultViewport: null, + devtools: true, + args: ["--window-size=1920,1080", "--window-position=1921,0", "--autoplay-policy=no-user-gesture-required"], + }); + + const page = await browser.newPage(); + + await page.goto("https://www.rtp.pt/play/p8157/e518677/telejornal", { + waitUntil: "load", + }); + + const stream = await getStream(page, { + audio: true, + video: true, + }); + + stream.pipe(file); + + setTimeout(async () => { + await stream.destroy(); + file.close(); + console.log("finished"); + }, 10000); +} +videoRecorder(); diff --git a/tsconfig.json b/tsconfig.json index 833f83e..cdb06a4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "exclude": ["examples", "dist", "extension"], + "include": ["src"], "compilerOptions": { /* Visit https://aka.ms/tsconfig.json to read more about this file */