Puppeteer屏幕录制:操作过程捕获全指南

Puppeteer屏幕录制:操作过程捕获全指南

1. 痛点与解决方案

你是否曾遇到以下场景:

  • 自动化测试中需要复现用户操作步骤
  • 需向团队展示网页交互过程而非静态截图
  • 构建产品演示时需要高质量操作视频

Puppeteer作为Chrome官方自动化工具,虽未直接提供屏幕录制API,但通过组合其截图能力与第三方视频处理库,可实现专业级操作过程捕获。本文将系统讲解3种录制方案,从基础实现到高级优化,帮助开发者快速掌握浏览器操作录制技术。

2. 核心原理与技术选型

2.1 录制原理对比

方案实现方式优势劣势适用场景
截图合成定时捕获页面截图,通过FFmpeg合成视频实现简单、兼容性好帧率受限、文件体积大基础演示、低帧率需求
CDP视频API使用Chrome DevTools Protocol直接录制原生支持、性能优异配置复杂、版本依赖高性能录制、专业测试
扩展录制器集成Chrome扩展实现录制功能功能全面、可控性强环境依赖高、部署复杂企业级应用、定制化需求

2.2 技术栈选择

  • 核心框架:Puppeteer 21+(确保CDP接口兼容性)
  • 视频处理:FFmpeg(跨平台视频处理工具)
  • 辅助库:node-cron(定时任务)、fluent-ffmpeg(视频处理封装)
  • 存储格式:WebM(浏览器原生支持)、MP4(广泛兼容)

3. 实现方案详解

3.1 基础方案:截图合成视频

3.1.1 实现流程

mermaid

3.1.2 代码实现
const puppeteer = require('puppeteer');
const fs = require('fs');
const { exec } = require('child_process');
const cron = require('node-cron');

// 配置参数
const RECORD_CONFIG = {
  output: 'recording.mp4',
  fps: 10,                  // 录制帧率
  quality: 80,              // 图像质量(0-100)
  timeout: 30000,           // 最大录制时长
  screenshotDir: './screenshots/'
};

// 确保截图目录存在
if (!fs.existsSync(RECORD_CONFIG.screenshotDir)) {
  fs.mkdirSync(RECORD_CONFIG.screenshotDir, { recursive: true });
}

async function startRecording() {
  // 启动浏览器
  const browser = await puppeteer.launch({
    headless: 'new',         // 使用最新无头模式
    defaultViewport: {
      width: 1280,
      height: 720
    }
  });
  const page = await browser.newPage();
  
  // 导航到目标页面
  await page.goto('https://example.com', {
    waitUntil: 'networkidle2'
  });
  
  let screenshotCount = 0;
  const startTime = Date.now();
  
  // 设置定时截图任务
  const task = cron.schedule(`*/${1000/RECORD_CONFIG.fps} * * * * *`, async () => {
    // 检查是否超时
    if (Date.now() - startTime > RECORD_CONFIG.timeout) {
      task.stop();
      await browser.close();
      await合成视频();
      return;
    }
    
    // 截取页面
    const screenshotPath = `${RECORD_CONFIG.screenshotDir}frame-${screenshotCount.toString().padStart(5, '0')}.png`;
    await page.screenshot({
      path: screenshotPath,
      fullPage: false,        // 仅捕获可视区域
      quality: RECORD_CONFIG.quality,
      type: 'png'
    });
    
    screenshotCount++;
  });
  
  // 模拟用户操作
  await performUserActions(page);
  
  // 操作完成后停止录制
  task.stop();
  await browser.close();
  await合成视频();
}

// 用户操作模拟函数
async function performUserActions(page) {
  await page.type('input[name="q"]', 'Puppeteer 屏幕录制', { delay: 100 });
  await page.click('input[type="submit"]');
  await page.waitForNavigation({ waitUntil: 'networkidle2' });
  await page.click('a:has-text("官方文档")');
  await page.waitForTimeout(2000);
}

// 视频合成函数
function合成视频() {
  return new Promise((resolve, reject) => {
    const ffmpegCommand = `ffmpeg -r ${RECORD_CONFIG.fps} -i ${RECORD_CONFIG.screenshotDir}frame-%05d.png -c:v libx264 -pix_fmt yuv420p ${RECORD_CONFIG.output}`;
    
    exec(ffmpegCommand, (error) => {
      if (error) {
        console.error('视频合成失败:', error);
        reject(error);
        return;
      }
      console.log(`视频已生成: ${RECORD_CONFIG.output}`);
      resolve();
    });
  });
}

// 启动录制
startRecording();
3.1.3 FFmpeg优化参数
# 基础转换命令
ffmpeg -r 10 -i frame-%05d.png -c:v libx264 output.mp4

# 优化参数(平衡质量与体积)
ffmpeg -r 10 -i frame-%05d.png -c:v libx264 -crf 23 -preset medium -pix_fmt yuv420p optimized-output.mp4

# 添加音频轨道
ffmpeg -r 10 -i frame-%05d.png -i narration.mp3 -c:v libx264 -c:a aac -strict experimental -shortest output-with-audio.mp4

3.2 高级方案:CDP视频录制API

3.2.1 实现原理

Chrome DevTools Protocol提供了Page.startScreencastPage.stopScreencast接口,可直接从浏览器获取视频流数据。Puppeteer通过page.target().createCDPSession()方法可访问这些底层接口。

3.2.2 代码实现
const puppeteer = require('puppeteer');
const fs = require('fs');

async function cdpBasedRecording() {
  const browser = await puppeteer.launch({
    headless: 'new',
    args: ['--enable-blink-features=AllowContentInitiatedDataUrlNavigations']
  });
  const page = await browser.newPage();
  await page.goto('https://example.com');
  
  // 创建CDP会话
  const client = await page.target().createCDPSession();
  
  // 设置视频参数
  const videoSettings = {
    format: 'webm',
    quality: 80,
    maxWidth: 1280,
    maxHeight: 720,
    everyNthFrame: 1       // 每帧都录制
  };
  
  // 创建视频文件流
  const videoStream = fs.createWriteStream('cdp-recording.webm');
  
  // 监听视频数据事件
  client.on('Page.screencastFrame', async (frame) => {
    // 写入视频数据
    videoStream.write(Buffer.from(frame.data, 'base64'));
    
    // 确认收到帧数据
    await client.send('Page.screencastFrameAck', {
      sessionId: frame.sessionId
    });
  });
  
  // 开始录制
  await client.send('Page.startScreencast', videoSettings);
  
  // 执行用户操作
  await performUserActions(page);
  
  // 停止录制
  await client.send('Page.stopScreencast');
  videoStream.end();
  await browser.close();
  
  console.log('CDP录制完成: cdp-recording.webm');
}

// 启动CDP录制
cdpBasedRecording();

3.3 企业级方案:扩展增强录制

对于需要高级功能(如麦克风输入、画中画效果、实时标注)的场景,可结合Chrome扩展实现增强录制:

  1. 扩展开发:创建包含录制功能的Chrome扩展
  2. Puppeteer集成:通过--load-extension加载扩展
  3. 消息通信:使用page.on('message')实现扩展与页面通信
  4. 录制控制:通过扩展API控制录制开始/停止/保存

核心代码示例:

// 加载扩展并启动录制
const browser = await puppeteer.launch({
  headless: false,  // 扩展需要可见窗口
  args: [
    `--load-extension=${pathToExtension}`,
    '--enable-extensions'
  ]
});

// 与扩展通信控制录制
page.on('message', (message) => {
  if (message.type === 'RECORDING_COMPLETE') {
    console.log('扩展录制完成:', message.filePath);
  }
});

// 发送录制命令
await page.evaluate(() => {
  // 调用扩展提供的录制API
  window.postMessage({
    type: 'START_RECORDING',
    options: {
      format: 'mp4',
      quality: 'high',
      includeAudio: true
    }
  }, '*');
});

4. 性能优化策略

4.1 录制性能调优

优化方向具体措施性能提升
图像优化使用JPEG格式(比PNG小30-50%)、降低分辨率存储效率+40%
帧率控制实现动态帧率(静态内容降低帧率)CPU占用-35%
区域录制使用clip参数仅录制关注区域数据量-60%+
异步处理截图与操作并行处理总耗时-25%

4.2 代码级优化示例

// 动态帧率实现
let lastContentHash = '';
async function智能截图(page, path) {
  // 获取页面内容哈希
  const contentHash = await page.evaluate(() => {
    return btoa(document.body.innerText.substring(0, 1000));
  });
  
  // 内容无变化时降低帧率
  if (contentHash === lastContentHash) {
    return false; // 不截图
  }
  
  lastContentHash = contentHash;
  
  // 执行截图
  await page.screenshot({
    path,
    clip: { x: 0, y: 0, width: 1024, height: 768 },  // 区域录制
    type: 'jpeg',
    quality: 85
  });
  
  return true;
}

5. 常见问题与解决方案

5.1 录制质量问题

问题原因分析解决方案
画面卡顿帧率不足或CPU负载过高降低帧率、优化操作脚本、启用硬件加速
图像模糊分辨率不匹配或压缩过度明确设置视口大小、调整quality参数 >75
颜色失真色彩空间转换问题FFmpeg添加-pix_fmt yuv420p参数
视频过大未启用压缩编码使用H.264编码、调整CRF参数(23-28)

5.2 兼容性问题

  • 无头模式限制:CDP录制和扩展录制在headless模式下可能受限,需使用headless: 'new'或禁用无头模式
  • 浏览器版本:确保Chrome版本≥88,以支持最新CDP录制API
  • 平台差异:Windows系统需要额外配置FFmpeg环境变量

6. 最佳实践与应用案例

6.1 自动化测试录制

在CI/CD流程中集成录制功能,自动捕获失败测试用例的操作过程:

// 测试失败时自动录制
try {
  await page.waitForSelector('#success-indicator', { timeout: 5000 });
} catch (error) {
  console.error('测试失败,开始录制错误场景');
  await startEmergencyRecording(page);  // 紧急录制最后操作
  throw error;  // 继续抛出错误,不影响测试流程
}

6.2 产品演示生成器

构建自动化演示生成工具,通过配置文件定义操作序列,批量生成产品演示视频:

// 演示配置文件示例
const demoConfig = {
  url: 'https://example.com/product',
  steps: [
    { action: 'type', selector: '#name', text: '演示用户', delay: 100 },
    { action: 'click', selector: '#start-tour' },
    { action: 'wait', duration: 3000 },
    { action: 'scroll', direction: 'down', distance: 500 }
  ],
  output: 'product-demo.mp4',
  resolution: '1280x720',
  fps: 15
};

// 基于配置自动执行并录制
await generateDemoFromConfig(demoConfig);

7. 总结与未来展望

Puppeteer屏幕录制技术通过灵活组合基础API与扩展工具,已能满足从简单演示到企业级应用的全场景需求。随着Chrome DevTools Protocol的不断完善,原生录制能力将进一步增强。未来发展方向包括:

  • WebRTC实时流传输集成
  • AI驱动的智能剪辑(自动识别关键操作)
  • WebGPU加速的视频编码
  • 云边协同的分布式录制系统

开发者可根据项目需求选择合适方案,基础场景推荐使用截图合成方案,对性能敏感的场景优先采用CDP原生录制,企业级应用可考虑扩展增强方案。通过本文提供的代码框架和优化策略,可快速构建稳定高效的浏览器操作录制系统。

8. 扩展资源

  • 官方文档:Puppeteer API文档(pptr.dev)、Chrome DevTools Protocol文档(chromedevtools.github.io/devtools-protocol)
  • 工具链:FFmpeg官方文档(ffmpeg.org)、node-cron(github.com/kelektiv/node-cron)
  • 代码库:puppeteer-recorder(github.com/checkly/puppeteer-recorder)、puppeteer-video-recorder(npm包)
  • 学习路径:Chrome开发者工具课程、Web性能优化实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值