Stream as a Dota 2 hero. Your face drives the model; the result goes into OBS.
Not affiliated with, endorsed by, or sponsored by Valve Corporation. Dota 2 and all associated names, models and artwork are Valve's property. This project is an independent tool and ships none of that content — see ASSETS.md.
Left: the phone, running Live Link Face — the dotted mask is ARKit tracking the operator. Right: the hero in Warudo. Same frame, same instant.
Code. Nothing else. No models, no textures, no sounds, no hero portraits, no extracted game files of any kind.
The tool finds the copy of Dota 2 you already own, reads the hero models out
of it on your machine, and builds the avatars into your own user folder.
Nothing Valve made is ever downloaded from here, and nothing Valve made ever
enters a commit. tools/check_no_assets.py enforces that in CI on every push.
That is a deliberate line, and it is where Valve's own published position points: they are fine with people making and monetising videos of their games, and explicitly not fine with taking assets out of their games and distributing those separately.
Every hero in the game, laid out the way Dota lays them out. Each tile carries a badge for what that hero's face can actually do — full expression, reduced, or none at all, because Valve did not model facial shapes for every hero and pretending otherwise would waste your time. Click one and the avatar changes.
The panel on the right shows the hero's ARKit shape count before you commit to it.
Type anywhere — it goes straight to search. Enter takes the first hit, Esc
clears, arrows navigate. Switching is measured rather than guessed: the progress
bar is driven by the real load time of that hero's .vrm.
It collapses to a narrow column, so it works as an OBS Custom Browser Dock
— the picker sits beside your scene list instead of in a separate window.
Point the dock at http://127.0.0.1:8796/.
Both the interface and the setup guide ship in all 28 languages Dota 2 itself
ships in — the list is read from the game's own countries_*.txt, not chosen
by us. If you can play the game in your language, you can install this in it.
English · Русский · Українська · 简体中文 · 繁體中文 · 한국어 · 日本語 · Deutsch · Français · Español · Español (LatAm) · Português · Português (BR) · Italiano · Polski · Čeština · Magyar · Română · Български · Ελληνικά · Türkçe · ไทย · Tiếng Việt · Nederlands · Dansk · Suomi · Norsk · Svenska
The interface follows your browser automatically. To override, use the
selector in the header, or http://127.0.0.1:8796/?lang=schinese.
The setup guide in each language covers what this is, what you need, the eight install steps and the honest limits. Everything past that — the wire formats, the framing maths, the security notes — stays in English here, because that is the part written for people who are going to read the code anyway.
The same build, one dropdown later. The Dota font, Radiance, has no Chinese
glyphs, so its unicode-range is pinned to Latin and everything else falls to
the system face — a font that covers half a string does not degrade gracefully,
it drops boxes into the middle of a word.
Interface strings live in one file, picker/i18n.js; each
guide is one file in docs/i18n/. The translations were
produced by the maintainer with machine assistance and are not
native-reviewed. If yours reads badly, fixing one file is a five-minute pull
request and genuinely welcome — you do not need to touch anything else.
Two checkers run before you open it, so a translation cannot quietly break the page or the docs:
py tools/check_i18n.py keys complete, {placeholders} intact, set matches Dota's
py tools/check_docs_i18n.py every guide present, links live, no section dropped
iPhone (Live Link Face) --UDP 11111--> bridge/llf_bridge.py
|
UDP 49983 (iFacialMocap)
v
Warudo --Spout2--> OBS
^
picker/picker_server.py (port 8796)
a Dota-style hero grid; switching is live,
the Spout output never drops
No iPhone? Warudo ships its own webcam face tracker, and everything downstream of it is identical — but see the note below: that path is untested here.
Five of the eight are "install a program the normal way, next-next-finish". You never open a terminal. You do type once: the address of your own PC, into the phone app, in step 8.
| Step | How long | |
|---|---|---|
| 1 | Install Steam if you have not, then Dota 2, and launch Dota once | ~70 GB download; 2 min to open |
| 2 | Install Warudo (free, Steam) and launch it once | 5 min |
| 3 | Install OBS (obsproject.com), open and close it | 2 min |
| 4 | Install Python 3.12 — tick "Add python.exe to PATH" | 3 min |
| 5 | Install Blender 3.6+ (blender.org) | 5 min |
| 6 | Download this project (green Code → Download ZIP), right-click the ZIP → Properties → tick Unblock, unzip, double-click install.bat |
2 min |
| 7 | It stops once and asks you to restart OBS. Do that, double-click install.bat again |
1 min |
| 8 | On the iPhone: install Live Link Face, add this PC as a target, set capture mode to ARKit | 5 min |
Step-by-step, with what each step looks like when it worked, and a troubleshooting section organised by symptom: docs/install.md
install.bat is safe to run as many times as you like. Each run skips what is
already done and stops at the first thing only a human can do, in plain English,
with the link — never a stack trace. Step 7 exists because OBS scans for plugins
only while it is starting up; that one is unavoidable and so it is counted.
What it does for you, so that the list above is only eight lines long: downloads and fingerprint-checks the tool that reads Dota's archive; indexes every hero out of your own game files (~7 s on a 70 GB install); builds a hero into an avatar (~20 s); starts Warudo through Steam; creates Warudo's scene, character, face tracking and the 20-node blueprint without which the tracking moves nothing; frames the camera; installs the OBS plugin, scene and source, sets the composite mode that stops a black box appearing around the head, and then measures whether transparency really arrives instead of assuming it; starts the phone bridge and the hero-select menu.
Two files you double-click, ever: install.bat (set up / start up) and
status.bat (where am I, and what address does my phone need). For anyone who
does want a terminal:
install.bat --status same as status.bat: changes nothing, starts nothing
install.bat --doctor the long technical checklist
install.bat --hero pudge build and load a different hero first
You need all of this. It is all free; none of it is optional.
| What | Why | |
|---|---|---|
| 1 | Windows 10/11 | Warudo and the Spout2 video pipe are Windows-only. There is no Linux or macOS path, and there will not be. |
| 2 | Dota 2, installed and launched once | The hero models come out of your copy. ~70 GB. |
| 3 | Warudo (Steam app 2079120) | Renders the avatar and receives the face tracking. |
| 4 | OBS | Gets Warudo's picture into your stream. |
| 5 | Python 3.10–3.12 | Runs the bridge and the build pipeline. |
| 6 | Blender 3.6+ | Assembles each hero into a .vrm. ~20 s per hero, then you never see it. |
| 7 | An iPhone X or newer | The face camera. This is the tested path. |
Source2Viewer CLI, which reads the Dota archive, used to be an eighth item here.
install.bat now downloads it and checks its SHA-256 against a pin in the
source, so it is no longer your problem.
About the iPhone. Live Link Face (free, App Store) needs Face ID hardware — iPhone X or newer. Everything here was built and measured against that path.
About the webcam — read this before you count on it. Warudo ships a MediaPipe
webcam tracker and there is a scene for it, so the capability is real. It has
not been verified end to end against the heroes this pipeline produces, it is a
different Warudo scene rather than a setting you flip, and install.bat does
not configure it. If you have no iPhone, expect to do some setup of your own, and
please open an issue with what you find. It is not promised.
Every hero is a different size — Pudge's head is three times Ember Spirit's — so each one gets its own camera, solved from the model's own geometry and then checked against the rendered pixels until the shot is a head-and-shoulders portrait. How that works, and why the Warudo window has a fixed size: docs/framing.md
install.bat |
the one entry point. Runs setup.ps1, which hands over to hexmask.wizard |
status.bat |
read-only version of the same thing, for people who never open a terminal |
hexmask/ |
wizard.py (the sequencer behind install.bat), path resolution, machine discovery, the doctor, the Warudo setup (setup_warudo.py, warudo_ctl.py), the OBS setup (obs.py), the background-process control (bridge_ctl.py) |
pipeline/ |
hero → .vrm build (Source2Viewer → Blender → VRM) |
picker/ |
the hero-select UI and Warudo's live-switch API client |
bridge/ |
Live Link Face → iFacialMocap bridge, GSI listener, OBS browser source |
vendor/ |
three.js, checked in so the OBS browser source works offline |
tools/ |
the no-assets firewall used by the pre-commit hook and CI |
Inside pipeline/, the three bl_*.py files run inside Blender's own Python
rather than the project's virtualenv.
Everything the tool produces goes to
%LOCALAPPDATA%\hexmask\ — never inside this folder. That is not
tidiness; it is the reason a game file cannot end up in a commit by accident.
Yes please — bug reports, hero-specific rig fixes, documentation. One rule matters more than all the others: no game files, ever. It is enforced by a pre-commit hook and a required CI check, not left to good intentions. See CONTRIBUTING.md, and SECURITY.md for anything you would rather not post in public.
MIT — see LICENSE. The MIT grant covers this source code only. It does not and cannot grant you any right to Valve's content. See ASSETS.md and TRADEMARKS.md.
Third-party components keep their own licences (NOTICE,
THIRD_PARTY_LICENSES.md). The three pipeline/bl_*.py
scripts are additionally GPL-2.0-or-later, because they import Blender's bpy.
The full scope note is in NOTICE; LICENSE deliberately carries the
bare MIT text so that automated licence detection recognises it.




