Turn 2–4 osu! replays into a side-by-side comparison video — real gameplay rendered by
danser-go, a styled neon overlay, and an animated results
card at the end. Drop a .osr on each side, hit Render, get a shareable .mp4. Supports
1v1, free-for-all up to four players, and 2v2 teams.
Works with both osu!stable and osu!lazer replays. Lazer replays that danser would falsely show as "failed" are auto-corrected.
- Go to the Releases page and download
CircleClash-windows.zipfrom the latest release. - Extract it into its own folder (e.g.
Documents\CircleClash). Inside you'll findCircleClash.exenext to a_internalfolder — keep them together. - Double-click
CircleClash.exe. On first run it creates aCircleClash-datafolder right next to it for everything it needs.
No Python, no ffmpeg install, nothing to add to your PATH. On first launch CircleClash downloads danser-go and ffmpeg automatically into that data folder, so the whole tool lives in one place you can move or delete as a unit.
You don't need to build anything. Running from source (below) is entirely optional — only useful if you want to modify the code.
A prebuilt Linux build (CircleClash-linux.zip) is attached to each release — extract it and run
the CircleClash binary inside. On first launch it provisions danser and ffmpeg into its own data
folder, just like the Windows app. (The bundled Chromium may need your distro's usual Chromium
runtime libraries present.) You can also still run from source if you
prefer.
Using the prebuilt app, you need nothing — it provisions danser and ffmpeg itself. The table below only applies if you choose to run from source.
| Requirement | Required? | Notes |
|---|---|---|
| Python 3.10 or newer | from source only | 3.10, 3.11, 3.12 all fine |
| ffmpeg | auto | downloaded on first run; or use a system ffmpeg if you already have one |
| danser-go | auto | downloaded automatically on first run |
| osu! API key | optional | adds avatars, ranks, flags and pp to the overlay |
| NVIDIA GPU | optional | only needed for the NVENC (GPU) encoders; everyone else uses x264/x265 |
On Linux you run CircleClash from source (no prebuilt release). It still downloads danser and ffmpeg for you on first run.
These steps use a virtual environment. On modern distros (Arch, Debian 12+, Fedora, …) a plain
pip install into the system Python is blocked with an "externally-managed-environment" error —
the virtual environment avoids that completely, so please don't skip it.
CircleClash downloads ffmpeg automatically on first run, so you don't have to install it. If you'd rather use your distro's ffmpeg, the package is listed alongside Python below.
Arch / CachyOS / Manjaro / EndeavourOS
sudo pacman -S --needed python python-pip git # add `ffmpeg` to use the system buildDebian / Ubuntu / Linux Mint / Pop!_OS
sudo apt update
sudo apt install python3 python3-pip python3-venv git # add `ffmpeg` for the system buildFedora / Nobara
sudo dnf install python3 python3-pip git
# optional system ffmpeg (RPM Fusion; Fedora's own build is codec-limited):
# sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm && sudo dnf install ffmpegopenSUSE
sudo zypper install python3 python3-pip git # add `ffmpeg` for the system buildNVENC (GPU encoding) on Linux also needs the proprietary NVIDIA driver. On the open/nouveau driver, stick to the x264 or x265 encoder in Settings.
git clone https://github.com/AmarilloNL/CircleClash.git
cd CircleClash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
playwright install chromium # <-- don't forget this; the overlay won't render without itpython renderer_gui.pyNext time, just cd CircleClash, run source .venv/bin/activate, then python renderer_gui.py.
You don't need this section to use CircleClash — download CircleClash-windows.zip from
Releases, extract it and run CircleClash.exe (see Download).
danser, ffmpeg and everything else are handled for you.
Optional: run from source on Windows (only if you want to modify the code)
Download the latest Python 3.x from python.org/downloads. In the installer, tick "Add python.exe to PATH" on the first screen before clicking Install.
Download the source (green Code → Download ZIP on GitHub) and unzip it. Then in PowerShell, inside the unzipped folder:
py -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
playwright install chromiumIf
Activate.ps1is blocked, run PowerShell once as Administrator and executeSet-ExecutionPolicy -Scope CurrentUser RemoteSigned, then try again.
py renderer_gui.pyffmpeg and danser are downloaded automatically on first run, just like the packaged app — you don't need to install them separately.
There's no prebuilt macOS app, and the automatic danser/ffmpeg download isn't available on macOS (neither ships an official macOS build), so on macOS you install both yourself via Homebrew below and point CircleClash at danser in Settings.
macOS has no NVENC, so in Settings choose the x264 or x265 encoder (the NVENC options are for NVIDIA GPUs only).
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"brew install python ffmpeg gitgit clone https://github.com/AmarilloNL/CircleClash.git
cd CircleClash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
playwright install chromiumpython renderer_gui.pyA short welcome appears and checks your setup. Then:
- danser-go + ffmpeg — if they aren't found, CircleClash offers to download them automatically (kept in the app's own data folder next to it). Choose No to point at an existing danser binary yourself.
- osu! Songs folder — open Settings and set this to your osu!
Songsfolder so beatmaps can be located. - osu! API (optional) — see below.
- Drag a
.osrreplay onto Player 1, and another onto Player 2 (or click a panel to browse). Need more? Click + Add player for up to four players (all on the same beatmap). - Pick each player's skin, the resolution and FPS.
- (Optional) Choose a Mode: Free-for-all ranks everyone individually, or 2v2 Teams (with four players) groups them into two teams — set each player's Team A/B.
- (Optional) Hit Preview and choose Overlay frame or Results card to render a quick still (a few seconds, no gameplay) and check names, avatars and colours look right first.
- Press Render. Progress shows in the bar; expand Show log for details.
- The finished
.mp4lands in your configured output folder.
The output layout adapts to the player count: 2 side by side, 3 in columns, 4 in a 2×2 grid. More players means each panel (and its gameplay) is smaller.
Tip: for quick iteration render at 1080p / 60. Full 4K / 240 looks great but takes much longer.
- Paths — danser binary, ffmpeg binary, your osu! Songs & Skins folders, output folder. (The packaged app fills in danser and ffmpeg for you.)
- osu! API — optional client id/secret (avatars, ranks, flags, pp).
- Timing — gameplay tail after the last note, end-card hold, results animation speed.
- Encoding
- Encoder:
x264/x265(CPU, works everywhere) orNVENC H.264/HEVC/AV1(NVIDIA GPU; AV1 needs an RTX 40-series). - Quality:
lossless → high → balanced → compact(quality vs file size). - Auto-fix osu!lazer false fails: on by default; only touches lazer replays.
- Encoder:
- Audio — independent P1/P2 music and P1/P2 hitsound volumes plus a master. Both players play the same song, so P2 music defaults to 0 (turn it up to crossfade, or mute a side's hitsounds to hear only one player).
- Visual — tune the danser HUD, background and cursor (all optional, off by default):
- Background: dark / dimmed / visible / blurred.
- Cursor size and trail length.
- Effects: bloom/glow, hit lighting, aim-error scatter meter, prominent unstable rate, pp breakdown (aim/speed/acc), per-side mods badge, ignore hitsound volume changes, disable storyboards.
- HUD elements: hide the pp counter, hit counts, hit-error bar, key overlay or combo (score + accuracy always show).
- Go to osu! → Settings → OAuth → New OAuth Application.
- Give it any name; the callback URL can be left blank.
- Copy the Client ID and Client Secret into CircleClash → Settings → osu! API.
Credentials are stored only on your machine and are never committed to git.
- "Playwright missing" / the overlay doesn't render — run
playwright install chromiuminside your activated virtual environment. - "ffmpeg not found" — let CircleClash fetch it: it downloads ffmpeg on first run, or you can set
the ffmpeg binary path in Settings → Paths. If you prefer a system ffmpeg, install it and make
sure it's on your
PATH, then reopen the app. - NVENC falls back to x264 — CircleClash pre-flights the GPU encoder and, if the bundled ffmpeg can't open it, automatically retries with your system ffmpeg before dropping to x264 (the log says what it did and why). On a capable GPU the usual cause is that the bundled ffmpeg is bleeding-edge and expects a newer driver than you have, while your distro's ffmpeg matches it — so the auto-retry normally just works. If it still can't, the log names the reason (no NVENC in either ffmpeg / driver's encode library not visible / AV1 needs an RTX 40-series). You can also pin a specific ffmpeg in Settings → Paths → ffmpeg binary (a custom path now takes priority over the auto-downloaded copy).
- The video won't play / looks broken in some players — HEVC and AV1 aren't supported everywhere. For maximum compatibility (and for sharing locally), use the x264 encoder.
externally-managed-environmenton pip (Linux) — you skipped the virtual environment. Create one withpython3 -m venv .venv && source .venv/bin/activate, then install again.- A replay's map can't be found — set your osu! Songs folder in Settings, and make sure the beatmap is actually downloaded in osu!.
CircleClash orchestrates external tools that it does not bundle — it fetches them at runtime:
- danser-go (GPL-3.0) — renders the gameplay. Downloaded from its official GitHub releases on first run.
- ffmpeg — mixes the audio and stitches the final video. A static build (from BtbN/FFmpeg-Builds) is downloaded on first run, or you can point at a system ffmpeg.
- Playwright — headless Chromium that renders the overlay and results card.
danser and ffmpeg are fetched at runtime and run as separate processes, so they keep their own
licenses and don't constrain this repository. CircleClash itself is released under the MIT license
(see LICENSE). Bundled and fetched components and their licenses are listed in
THIRD-PARTY-NOTICES.md.
A ready-to-use GitHub Actions workflow is included at .github/workflows/build.yml. It builds a
one-folder PyInstaller app for Windows and Linux (a matrix
build), zips each, and attaches them to the GitHub Release. To cut a release:
git tag v1.3.0
git push origin v1.3.0The workflow then produces CircleClash-windows.zip and CircleClash-linux.zip and uploads them
to the release for that tag. You can also trigger a test build manually from the Actions tab
(Run workflow).
How the packaging works (worth knowing if you tweak it):
- One executable, two roles. The GUI relaunches itself with
--run-pipelineto do the actual render, so a single PyInstaller build is both the app and its render worker. - One folder (
--onedir), zipped. The build is a folder (an executable next to an_internaldirectory) that gets zipped for the release. Unlike--onefile, it doesn't unpack a ~300-400 MB bundle to a temp dir on every launch, so it starts near-instantly — which matters here because the self-relaunch above would otherwise pay that cost twice (GUI + each render). - Chromium is bundled. The overlay/results card is rendered with Playwright's Chromium, installed
with
PLAYWRIGHT_BROWSERS_PATH=0and collected via--collect-all playwright; the frozen app sets the same variable so it loads the bundled browser. (For a much smaller build, the alternative is to render the overlay with Qt/Pillow instead of HTML and drop Chromium entirely.) - danser and ffmpeg are auto-provisioned, not embedded — on first run the app downloads danser (GPL-3.0, from its official GitHub release) and a static ffmpeg build (GPL, from BtbN/FFmpeg-Builds) into its data folder. They run as separate processes, so CircleClash's own MIT license is unaffected and the binaries keep their own licenses. This keeps the executable small and the downloads easy to update.
- Portable by default — the packaged app stores danser, ffmpeg, render-songs and config in a
CircleClash-datafolder next to the executable, so the whole tool lives in one place the user controls. If that location isn't writable (e.g. Program Files) it falls back to the per-user data dir. From source you can opt in withCIRCLECLASH_PORTABLE=1(or=/path/to/anchor).
First CI run tip: if Chromium isn't found at runtime, double-check the
PLAYWRIGHT_BROWSERS_PATH: '0'env on both the install and build steps — that's the usual culprit.