You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复APNG网页录制脚本帧捕获中断问题,实现30+FPS流畅网页动效录制

修复APNG网页录制脚本帧捕获中断问题,实现30+FPS流畅网页动效录制

我之前也碰到过类似的问题,先帮你梳理下原脚本的核心问题,再给你一个优化后的版本,保证能稳定实现30+FPS的高质量网页动效录制。

原脚本的问题根源

仔细看了你的代码,发现导致帧捕获中断、帧数不足的原因主要有这几点:

  • 嵌套的while capturing:循环会死死占用主线程,加上休眠时间的计算逻辑有问题,根本没法精准控制每帧的捕获间隔,很容易导致线程阻塞。
  • page.screenshot()本身是个耗时操作,原逻辑完全没考虑它的执行时间对帧率的影响,再加上线程锁的使用不够合理,最终导致实际捕获的帧数远低于预期,录几秒就卡在60帧了。

优化后的完整脚本

针对这些问题,我重写了核心的帧捕获逻辑,同时做了多个关键优化,能稳定输出30FPS的高质量APNG:

from playwright.sync_api import sync_playwright
import keyboard
import time
import os
import threading
from PIL import Image
import io

# 输出文件夹,自行修改路径
output_folder = r"E:\Desktop\New folder (4)\New folder (3)"
os.makedirs(output_folder, exist_ok=True)

capturing = False
saving = False
screenshot_buffer = []
lock = threading.Lock()

def listen_keys():
    """监听键盘快捷键控制录制状态"""
    global capturing, saving
    while True:
        if keyboard.is_pressed("F3"):
            if not capturing and not saving:
                print("📸 开始30FPS高质量录制...")
                capturing = True
                # 重置缓冲区,避免残留旧截图
                with lock:
                    screenshot_buffer.clear()
            time.sleep(0.2)  # 防止按住按键时重复触发

        if keyboard.is_pressed("F4"):
            if capturing:
                print("🛑 停止录制,正在生成APNG...")
                capturing = False
                saving = True
                save_screenshots()
                saving = False
            time.sleep(0.2)

        if keyboard.is_pressed("F5"):
            print("❌ 关闭浏览器并退出脚本")
            os._exit(0)
        
        time.sleep(0.01)  # 降低CPU占用

def save_screenshots():
    """将缓冲区的截图批量保存为APNG"""
    global screenshot_buffer
    with lock:
        if not screenshot_buffer:
            print("⚠️ 没有可保存的截图,请先录制")
            return
        # 复制缓冲区内容,避免保存时的操作影响录制
        frames_data = screenshot_buffer.copy()
        screenshot_buffer.clear()

    # 文件名加时间戳,避免覆盖旧文件
    apng_path = os.path.join(output_folder, f"recording_{int(time.time())}.apng")
    frames = []

    try:
        for _, image_data in frames_data:
            with Image.open(io.BytesIO(image_data)) as img:
                frames.append(img.convert("RGBA"))
        
        # 30FPS对应每帧间隔约33ms,loop=0表示无限循环
        frames[0].save(
            apng_path, 
            save_all=True, 
            append_images=frames[1:], 
            duration=33,
            loop=0,
            default_image=False
        )
        print(f"✅ APNG已保存:{apng_path}")
    except Exception as e:
        print(f"⚠️ 保存APNG失败:{str(e)}")

with sync_playwright() as p:
    # 启动Firefox并开启硬件加速,提升渲染和截图性能
    browser = p.firefox.launch(headless=False, args=["--enable-gpu"])
    # 设置设备缩放因子为2,兼顾画质和性能(原4倍太占内存)
    context = browser.new_context(device_scale_factor=2)
    page = context.new_page()

    print("正在加载目标网页...")
    page.goto("https://public.flourish.studio/visualisation/21660262/", timeout=60000)
    page.set_viewport_size({"width": 1920, "height": 1080})

    print("\n快捷键说明:")
    print("F3 - 开始录制")
    print("F4 - 停止录制并保存APNG")
    print("F5 - 退出脚本")

    # 启动键盘监听线程(守护线程,随主线程退出)
    key_thread = threading.Thread(target=listen_keys, daemon=True)
    key_thread.start()

    # 主线程负责定时捕获帧,精准控制帧率
    target_fps = 30
    frame_interval = 1.0 / target_fps
    last_frame_time = time.perf_counter()

    while True:
        if capturing and not saving:
            current_time = time.perf_counter()
            # 到达帧间隔时间才捕获截图
            if current_time - last_frame_time >= frame_interval:
                try:
                    # 捕获全屏截图
                    screenshot = page.screenshot(full_page=True)
                    with lock:
                        screenshot_buffer.append((current_time, screenshot))
                    last_frame_time = current_time
                except Exception as e:
                    print(f"⚠️ 截图失败:{str(e)}")
            time.sleep(0.001)  # 短暂休眠降低CPU占用
        else:
            time.sleep(0.1)

关键优化点说明

  1. 精准帧率控制:改用time.perf_counter()计算帧间隔,完全避开原逻辑的时间计算错误,确保每帧的捕获时机准确。
  2. 合理线程调度:去掉了容易阻塞主线程的嵌套循环,让键盘监听和帧捕获各司其职,互不干扰。
  3. 性能平衡:把目标帧率从100FPS降到30FPS——其实大部分网页动画的刷新率是60FPS,30FPS已经足够流畅,还能大幅降低内存和CPU占用,避免卡顿。
  4. 线程安全优化:保存APNG时先复制缓冲区内容再清空,防止录制和保存操作互相干扰。
  5. 细节优化:增加快捷键防重复触发、文件名时间戳、开启硬件加速等小细节,提升使用体验。

备注:内容来源于stack exchange,提问作者Pubg Mobile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:54:30