/** * Setup and configure a Puppeteer page * @param {Browser} browser - Puppeteer browser instance * @param {Object} options - Configuration options * @param {number} options.width - Page width * @param {number} options.height - Page height * @returns {Promise} Configured Puppeteer page */ async function setupPage(browser, { width, height }) { const page = await browser.newPage(); // Reduce memory usage by disabling caching await page.setCacheEnabled(false); // Inject CSS early to prevent white flash during page load await page.evaluateOnNewDocument(() => { const style = document.createElement('style'); style.textContent = ` html, body { background-color: #000 !important; } `; document.head?.appendChild(style) || document.documentElement.appendChild(style); }); return page; } /** * Wait for page to be fully loaded with stylesheet * @param {Page} page - Puppeteer page * @param {string} url - URL to navigate to * @returns {Promise} True if page loaded successfully */ async function waitForPageFullyLoaded(page, url) { try { // Wait for DOM content to load - no artificial delay, stream starts immediately await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 }); return true; } catch (err) { console.error('Page load error:', err.message); // Still show the page even if timeout occurs return true; } } /** * Hide logo elements on the page * @param {Page} page - Puppeteer page */ async function hideLogo(page) { try { await page.evaluate(() => { const images = document.querySelectorAll('img'); images.forEach(img => { if (img.src && img.src.includes('Logo3.png')) { img.style.display = 'none'; } }); }); } catch (err) { // Silent } } /** * Start smooth auto-scrolling on the page * @param {Page} page - Puppeteer page * @param {Object} options - Scrolling options * @param {number} options.pauseAtTop - Seconds to wait at top before scrolling (default: 30) * @param {number} options.fps - Frame rate for smooth scrolling (default: 30) * @returns {Function} Stop function to cancel scrolling */ async function startAutoScroll(page, { pauseAtTop = 30, fps = 30 } = {}) { let stopScrolling = false; const stopFunction = () => { stopScrolling = true; }; // Inject scrolling logic into the page await page.evaluate((pauseMs, captureFrameRate) => { window.__autoScrollState = { stopScrolling: false, isScrolling: false }; function smoothScroll() { if (window.__autoScrollState.stopScrolling) return; const maxScroll = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight ) - window.innerHeight; if (maxScroll <= 0) { // Page is not scrollable, just wait setTimeout(() => { if (!window.__autoScrollState.stopScrolling) { smoothScroll(); } }, pauseMs); return; } // Wait at top, then start smooth scroll setTimeout(() => { if (window.__autoScrollState.stopScrolling) return; // Slow scroll speed for smooth appearance // At 60fps with 30px/s = 0.5 pixels per frame const pixelsPerSecond = 30; const pixelsPerFrame = pixelsPerSecond / captureFrameRate; const frameInterval = 1000 / captureFrameRate; function scrollDown() { if (window.__autoScrollState.stopScrolling) return; let currentPos = window.scrollY; const interval = setInterval(() => { if (window.__autoScrollState.stopScrolling) { clearInterval(interval); return; } currentPos += pixelsPerFrame; if (currentPos >= maxScroll) { window.scrollTo(0, maxScroll); clearInterval(interval); setTimeout(() => { if (!window.__autoScrollState.stopScrolling) { scrollUp(); } }, 2000); } else { window.scrollTo(0, currentPos); } }, frameInterval); } function scrollUp() { if (window.__autoScrollState.stopScrolling) return; let currentPos = window.scrollY; const interval = setInterval(() => { if (window.__autoScrollState.stopScrolling) { clearInterval(interval); return; } currentPos -= pixelsPerFrame; if (currentPos <= 0) { window.scrollTo(0, 0); clearInterval(interval); if (!window.__autoScrollState.stopScrolling) { smoothScroll(); } } else { window.scrollTo(0, currentPos); } }, frameInterval); } scrollDown(); }, pauseMs); } // Start scrolling smoothScroll(); }, pauseAtTop * 1000, fps); return stopFunction; } module.exports = { setupPage, waitForPageFullyLoaded, hideLogo, startAutoScroll };