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

