Skip to content

Repository files navigation

Frameseer

CI Release License

A game performance advisor for Windows, in pure-stdlib Python. Frameseer reads your actual hardware, pulls per-game facts from PCGamingWiki, and recommends graphics settings with a one-line rationale for every setting. Then she measures real frametimes with PresentMon, and refines her advice from what actually happened — refusing to call anything a win that's inside the noise floor.

Zero pip dependencies. ~2,400 lines of winreg + CIM + sqlite3 + standard library.

> python -m frameseer recommend 1091500

Here is where I'd begin. Yours to apply, in the menus.

Cyberpunk 2077 — profile v1
Target: 2560x1080@180Hz, 90 fps

Settings:
  Resolution -> 2560x1080
      :: Native panel resolution; scaling is done by the upscaler, not by dropping to a non-native mode...
  Upscaling -> FSR (Quality)
      :: AMD-native upscaler; Quality mode reclaims real GPU headroom at 2560x1080 with minimal image loss.
  Texture Quality -> High, not Ultra
      :: 8 GB VRAM is a real ceiling at 2560x1080; Ultra textures risk exceeding the pool and causing hitching.
  ...

Why this exists

"Can You Run It" and the settings guides on YouTube answer the wrong question. CYRI knows the game's requirements but not your machine (its detection is an ActiveX relic); a guide knows the reviewer's 4090, not your 6600 XT on an ultrawide with an aging 8-thread CPU. And auto-"optimizers" (GeForce Experience-style) apply opaque presets with no reasoning and no follow-up measurement.

Frameseer's loop is: read the machine → read the game → recommend with reasons → measure → learn.

  • Hardware comes from the machine itself — CIM queries plus registry reads, including the real VRAM (WMI's AdapterRAM is a uint32 that caps at 4 GB, so Frameseer reads the 64-bit HardwareInformation.qwMemorySize from the display-class registry key instead).
  • Recommendations branch on the actual bottleneck: a few-thread/low-clock CPU pulls the fps target down and the CPU-bound levers (draw distance, crowd density) back; VRAM pressure caps textures; the GPU vendor picks the upscaler; the install drive's media type (NVMe/SATA/HDD, read via PowerShell) feeds streaming-stutter advice.
  • Measurement is real frametimes at the present boundary via PresentMon (AMD Adrenalin bundles it), summarized as avg / 1% low / 0.1% low / frametime stddev.
  • Learning is deliberately skeptical: a change only "helped" if it clears both a relative (≥5%) and an absolute (≥3 fps) noise floor, one scene is labelled weak evidence, and failed levers are never re-proposed.

Advisor, not auto-applier. Frameseer never edits a game's config files or driver settings — per-game configs differ wildly, auto-editing risks corrupting saves, and launchers overwrite changes. She recommends; you apply it in the menu; she measures whether it worked.

Architecture

python -m frameseer <cmd>      __main__.py (CLI: hw, games, fetch, recommend, measure, learn, show, report)
                              |-- hardware.py    CIM + registry inventory (incl. qwMemorySize VRAM fix)
                              |-- gamedata.py    PCGamingWiki wikitext fetch + template parser (+ CYRI probe)
                              |-- recommend.py   bottleneck reasoning -> per-setting rationales
                              |-- measure.py     PresentMon capture + CSV parsing -> fps percentiles
                              |-- learn.py       noise-floor judging, single-lever next-step proposals
                              |-- db.py          SQLite: hardware, games, versioned profiles, sessions, tweaks
                              |-- telemetry.py   optional outbound POST (disabled by default)
                              '-- voice.py       Frameseer's register (thin flavor layer; the data is the point)

Everything persists in one SQLite file (frameseer_data/frameseer.db): the hardware profile, per-game PCGW cache, versioned recommendation profiles, every measured session (tagged with the profile version and a scene note), and the tweak history with outcomes (pending / helped / no_help / reverted).

The PCGamingWiki client is a real wikitext parser — balanced {{...}} template scanning with top-level | splitting — that extracts the System requirements template (min/rec) and Game data/config locations from one API request per game, cached thereafter.

Quick start

git clone https://github.com/casul185/frameseer.git && cd frameseer
copy config.example.json config.json      # optional; defaults work
python -m frameseer hw                       # read this machine
python -m frameseer recommend 1091500        # Steam app id or a game name
# ... apply settings in-game, play, then while the game is running:
python -m frameseer measure 1091500 --secs 30 --scene "city, driving"
python -m frameseer learn 1091500            # judge results, propose ONE next tweak
python -m frameseer show 1091500             # profile + session history + pending tweaks

Configuration

config.json next to the package (see config.example.json); every key is optional.

Key Default Meaning
node_name "gaming-pc" Label used in telemetry payloads
data_dir "" (→ ./frameseer_data) Where the SQLite db, PCGW cache, and raw PresentMon CSVs live
presentmon_path "" Full path to PresentMon-x64.exe; empty probes the AMD Adrenalin bundle locations
telemetry.enabled false Master switch for the optional report command's outbound POST
telemetry.endpoint / token "" POST target; optional Authorization: Bearer token

Limitations (honest)

  • Windows only (CIM, registry, PresentMon). Steam-centric game resolution; non-Steam games work by name but lose install-drive detection.
  • PresentMon capture needs admin rights (ETW), and only sees titles actively presenting frames — UWP/protected/DRM-wrapped titles may produce nothing, and a menu screen produces nothing useful.
  • One capture is one scene. Frameseer's own output repeatedly says so: treat a single session as a hunch, not a verdict.
  • Requirement text on PCGamingWiki is free-form; Frameseer extracts it faithfully but only draws coarse conclusions from it ("this title lists only modest GPUs").
  • CPU boost clocks are not reliably readable via WMI — reported as unknown rather than guessed.
  • The recommendation engine is heuristic, tuned for "demanding modern title" as the default stance. It aims to be a good starting profile; the measure/learn loop is what makes it yours.

Requirements

  • Windows 10/11. PresentMon (bundled with AMD Adrenalin; or point presentmon_path at any PresentMon build).
  • Python ≥ 3.8 (syntactic minimum, verified with vermin; developed and run on 3.11+). No packages — stdlib only.

Staying up to date

To be notified of new releases, Watch this repo on GitHub → the Custom dropdown → check Releases. The full list lives at github.com/casul185/frameseer/releases.

Frameseer also checks for updates herself: on an interactive run, at most once per 24h, she makes a best-effort call to GitHub and, if a newer release exists, prints a single one-line notice to stderr. She never auto-updates and never nags. To disable this entirely, set FRAMESEER_NO_UPDATE_CHECK=1 in your environment.

Support

If this project is useful to you, you can support it at ko-fi.com/casul185.

License

MIT — see LICENSE.

Related

GPU VRAM is read via a sibling project — amd-vram-detection — which works around the WMI 4 GB cap.

About

Windows game performance advisor (pure-stdlib Python): reads your hardware, pulls per-game facts, recommends settings, and measures real frametimes with PresentMon.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages