remote-rdr / utils /HtmlRender.js
shiveshnavin's picture
Fix fixed video
15268b5
import { chromium } from 'playwright';
import { attachRecorder } from 'playwright-recorder-plus';
import fs from 'fs';
import path from 'path';
export class HtmlRender {
constructor() {
this.browser = null;
this.page = null;
}
async init() {
if (!this.browser) {
this.browser = await chromium.launch();
this.page = await this.browser.newPage();
}
}
async renderFrame(html, htmlFile, outFilePath, options = {}) {
console.log('Rendering frame from', html?.substring(0, 100) || htmlFile, '->', outFilePath)
await this.init();
if (html) {
await this.page.setContent(html, { waitUntil: 'networkidle' });
} else if (htmlFile) {
await this.page.goto(`file://${htmlFile}`, { waitUntil: 'networkidle' });
} else {
throw new Error('Either html or htmlFile must be provided.');
}
await this.page.screenshot({ path: outFilePath, ...options });
}
async renderVideo(html, htmlFile, outFilePath, durationSec, options = {}) {
console.log('Rendering video from', html?.substring(0, 100) || htmlFile, '->', outFilePath, "duration", durationSec)
if (!this.browser) {
this.browser = await chromium.launch();
}
const vw = (options.viewport && options.viewport.width) || 1080;
const vh = (options.viewport && options.viewport.height) || 1920;
const context = await this.browser.newContext({
viewport: { width: vw, height: vh }
});
const page = await context.newPage();
if (html) {
await page.setContent(html, { waitUntil: 'networkidle' });
} else if (htmlFile) {
const absPath = path.isAbsolute(htmlFile) ? htmlFile : path.join(process.cwd(), htmlFile);
await page.goto(`file://${absPath}`, { waitUntil: 'networkidle' });
}
// Force a layout/paint
await page.evaluate(() => document.body.offsetHeight);
// Attach high-quality recorder
const recorder = await attachRecorder(page, {
path: outFilePath,
fps: options.fps || 30,
ffmpegOptions: {
// Ensuring high quality for the render farm
crf: 18,
preset: 'veryfast'
}
});
// Wait for the requested duration
await page.waitForTimeout(durationSec * 1000);
// Stop and finalize
await recorder.stop();
await recorder.finalized;
await page.close();
await context.close();
}
async close() {
if (this.browser) {
await this.browser.close();
this.browser = null;
this.page = null;
}
}
}