{"id":48102483,"url":"https://github.com/danthi123/lolproxychat","last_synced_at":"2026-05-31T05:01:34.334Z","repository":{"id":343158434,"uuid":"1176407370","full_name":"danthi123/LoLProxyChat","owner":"danthi123","description":"Proximity voice chat for League of Legends","archived":false,"fork":false,"pushed_at":"2026-03-09T19:35:20.000Z","size":2264,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-04T16:31:13.155Z","etag":null,"topics":["league-of-legends","overwolf","proximity-chat","webrtc"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danthi123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-09T01:47:44.000Z","updated_at":"2026-03-09T19:35:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/danthi123/LoLProxyChat","commit_stats":null,"previous_names":["danthi123/lolproxychat"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/danthi123/LoLProxyChat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danthi123%2FLoLProxyChat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danthi123%2FLoLProxyChat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danthi123%2FLoLProxyChat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danthi123%2FLoLProxyChat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danthi123","download_url":"https://codeload.github.com/danthi123/LoLProxyChat/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danthi123%2FLoLProxyChat/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33719601,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["league-of-legends","overwolf","proximity-chat","webrtc"],"created_at":"2026-04-04T15:45:29.577Z","updated_at":"2026-05-31T05:01:34.325Z","avatar_url":"https://github.com/danthi123.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LoLProxChat\n\nProximity voice chat for League of Legends. Hear nearby players with volume that scales by in-game distance, tied to minimap vision — if you can't see them, you can't hear them.\n\nStandalone Windows desktop app built with Tauri 2 + WebView2. No Overwolf, no third-party voice service.\n\n## Install\n\nDownload the latest `proxchat.exe` from [Releases](https://github.com/danthi123/LoLProxyChat/releases/latest). It's a single portable executable — no installer.\n\n**Requirements:** Windows 10 1809+ or Windows 11. WebView2 Runtime (ships with Windows 11; pushed via Edge on Windows 10).\n\nLaunch the exe before or during a League match. The overlay auto-attaches beside the minimap once a game is detected.\n\n## How It Works\n\n1. **Game detection** — Polls the League Client (LCU) for game phase, then the Live Client Data API for player roster and your summoner identity. No memory reading.\n2. **Position detection** — Win32 BitBlt captures the minimap region, HSV color filtering + blob detection finds champion icons, and an ONNX champion classifier identifies which blob is your own champion.\n3. **Signaling** — Players in the same game join a deterministic WebSocket room (room ID = hash of sorted player names) on a self-hosted Node server.\n4. **Voice** — WebRTC peer-to-peer audio between players; no audio touches any server.\n5. **Proximity volume** — Server-side AES-GCM encrypted position blobs + volume computation, so no client learns another player's exact position. Logarithmic falloff up to 1200 game units.\n6. **Audio processing** — RNNoise WASM for noise suppression + voice activity detection; Opus at 128 kbps with DTX for bandwidth efficiency.\n\n## Architecture\n\n```\nproxchat.exe (Tauri 2)\n├── Rust backend       — Win32 screen capture, LCU/Live Client polling, window positioning\n└── WebView2 frontend  — orchestrator, signaling, WebRTC, CV, ONNX, RNNoise\n\nserver/                — Node WebSocket + HTTP signaling server\n├── /ws                — WebSocket upgrade for room join, signaling, presence\n├── /compute-volumes   — POST: encrypted position blobs → per-peer volumes\n├── /turn-credentials  — GET: ephemeral HMAC TURN credentials\n└── /health            — health check\n```\n\n**Key client services** (under `src/services/`):\n- `Orchestrator` — wires game state → tracking → signaling → audio\n- `TrackingService` — minimap CV pipeline (capture → HSV mask → blob detect → classifier)\n- `ChampionClassifier` — ONNX Runtime Web (WASM backend) inference\n- `AudioService` — WebRTC audio + RNNoise VAD/PTT + per-peer volume control\n- `SignalingService` — WebSocket presence and signal relay\n- `PeerConnection` — WebRTC with Opus 128 kbps DTX\n- `VolumeClient` — calls `/compute-volumes` with encrypted blobs\n- `DataChannelService` — WebRTC data channels for encrypted blob exchange\n- `GameStateService` — wraps Tauri commands for LCU + Live Client Data\n\n**Rust commands** (under `src-tauri/src/`):\n- `capture.rs` — `set_capture_bounds`, `capture_minimap` (Win32 GDI BitBlt)\n- `lcu.rs` — `check_league_running`, `get_game_state`, `get_live_client_data`, `read_text_file`\n- `main.rs` — `position_overlay`, `get_screen_size`; sets `WDA_EXCLUDEFROMCAPTURE` on the overlay window so its debug paint doesn't feed back into the next capture\n\n## Build From Source\n\n### Prerequisites\n- [Node.js](https://nodejs.org/) 18+\n- [Rust](https://rustup.rs/) (stable toolchain)\n- Windows 10/11 with the WebView2 SDK headers (installed automatically by Tauri on first build)\n\n### Build\n\n```bash\nnpm install\ncp .env.example .env       # optional — defaults to https://proxchat.dant123.com\nnpx tauri build\n```\n\nThe portable exe lands at `src-tauri/target/release/proxchat.exe`.\n\nFor iterative dev, rebuild and relaunch:\n```bash\nnpx tauri build \u0026\u0026 src-tauri/target/release/proxchat.exe\n```\n(No `tauri dev` workflow yet — there's no webpack dev server configured.)\n\n### Client environment\n\nOnly one variable, baked in at build time:\n\n| Variable | Default | Description |\n|---|---|---|\n| `PROXCHAT_SERVER` | `https://proxchat.dant123.com` | Base URL of the signaling server. WebSocket URL is derived (`https://` → `wss://`). |\n\n## Self-Hosting the Signaling Server\n\nThe server is a small Node app (~500 LOC) that replaces what used to be a stack of Supabase containers. Run it under Docker on any always-on host with HTTPS.\n\n```bash\ncd server\ndocker compose -f ../docker-compose.proxchat.yml up -d\n```\n\nOr run it directly:\n\n```bash\ncd server\nnpm install\nnpm run build \u0026\u0026 npm start\n```\n\n### Server environment\n\n| Variable | Required | Description |\n|---|---|---|\n| `PORT` | no (default `3100`) | HTTP/WebSocket port |\n| `ENCRYPTION_KEY` | yes | 64-char hex (256-bit) key for AES-GCM position encryption |\n| `TURN_SERVER` | optional | TURN/STUN server hostname (returned to clients) |\n| `TURN_SECRET` | optional | coturn shared secret for HMAC credential generation |\n\nIf `TURN_SERVER`/`TURN_SECRET` are unset, clients fall back to Google STUN only — fine for most NAT setups, may fail behind symmetric NAT.\n\nA working `docker-compose.proxchat.yml` is included at the repo root with the server + coturn sidecar. Front it with a TLS-terminating reverse proxy (Caddy, nginx, Traefik) that proxies `/` to `:3100` and supports WebSocket upgrades.\n\n### Tests\n\n```bash\ncd server \u0026\u0026 npm test     # vitest — rooms, volumes, turn credentials\nnpm test                  # jest — core logic (room hashing, proximity, etc)\n```\n\n## Project Structure\n\n```\nsrc/\n├── background/          — orchestrator entry point (loaded into the overlay window)\n├── overlay/             — overlay window (HTML/CSS/TS)\n├── core/                — pure logic modules (tested)\n│   ├── config.ts        — server URL, ICE servers\n│   ├── types.ts\n│   ├── room.ts          — deterministic room ID hashing\n│   ├── proximity.ts     — volume falloff math\n│   ├── map-calibration.ts\n│   ├── template-match.ts\n│   └── streamer-detect.ts\n└── services/            — runtime services (see Architecture above)\n\nsrc-tauri/               — Tauri 2 Rust backend\n├── src/\n│   ├── main.rs\n│   ├── capture.rs\n│   └── lcu.rs\n├── Cargo.toml\n└── tauri.conf.json\n\nserver/                  — Node signaling server\n├── src/\n│   ├── index.ts         — HTTP + WebSocket server\n│   ├── ws-handler.ts    — join, signal, position, presence\n│   ├── rooms.ts         — room state\n│   ├── volumes.ts       — AES-GCM blob encryption + volume math\n│   ├── turn.ts          — TURN HMAC credential generation\n│   └── types.ts\n├── tests/\n└── Dockerfile\n\nmodels/\n├── champion_classifier.onnx\n└── champion_labels.json\n\nscripts/\n└── train_champion_classifier.py\n\ndocs/\n├── SETUP.md             — deeper deployment + self-host guide\n└── plans/               — historical design + implementation plans\n```\n\n## Releases\n\nNew builds are published to [GitHub Releases](https://github.com/danthi123/LoLProxyChat/releases). To cut a release:\n\n```bash\n# bump src-tauri/Cargo.toml version\nnpx tauri build\ngh release create v0.1.X src-tauri/target/release/proxchat.exe \\\n  --title \"v0.1.X — short summary\" \\\n  --notes \"release notes here\"\n```\n\nUsers can always grab the most recent via:\n```\nhttps://github.com/danthi123/LoLProxyChat/releases/latest/download/proxchat.exe\n```\n\n## Acknowledgements\n\n- [LeagueMinimapDetectionCNN](https://github.com/Maknee/LeagueMinimapDetectionCNN) — reference code for minimap detection\n- [League of Legends Wiki](https://wiki.leagueoflegends.com) — champion circle icon assets used for classifier training\n- [RNNoise](https://jmvalin.ca/demo/rnnoise/) — noise suppression via [@jitsi/rnnoise-wasm](https://github.com/nicknisi/rnnoise-wasm)\n- [Tauri](https://tauri.app) — desktop app framework\n\n## License\n\n[PolyForm Noncommercial 1.0.0](LICENSE) — source available for personal and noncommercial use only.\n\nChampion icon assets from the [League of Legends Wiki](https://wiki.leagueoflegends.com) (CC BY-SA 3.0) were used for model training only and are not distributed with this software.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanthi123%2Flolproxychat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanthi123%2Flolproxychat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanthi123%2Flolproxychat/lists"}