- Python 50%
- Swift 41%
- PowerShell 9%
Ceetuber #
A local VTuber template with swappable avatars and their own behaviors. The default is a rectangle with eyes: no model download or rig required. Cee is included as a more elaborate example, with cloth deformation, a floppy hat, physical ornaments, and reflections.
Live demo · Build an avatar · Technical walkthrough · iPhone setup
Run locally #
Install Node.js 22 or newer:
git clone https://tangled.org/cee.wtf/ceetuber
cd ceetuber
node serve.mjs
Open http://127.0.0.1:8766/. Pick an avatar and try the sliders. A phone or controller is optional. Keep the terminal running; opening index.html from disk will fail because modules need HTTP.
There are no runtime npm dependencies or build step. dist/ contains maintained browser source and bundled Three.js. The server supports Windows, macOS and Linux; the background Xbox bridge is Windows-only. Rendering needs WebGL2. The hosted demo supports sliders and browser gamepads; iPhone tracking and shared OBS input use the local server.
Use Load GLB… to preview a local self-contained model, with head/eye mapping and blink shape keys. Imports stay in the current tab and are not shared with OBS. See local model requirements.
The rectangle is procedural and loads quickly. Selecting Cee downloads its roughly 20 MB GLB and textures. Blender is only needed to edit/rebuild that example's assets.
Plug in a character #
Each avatar exports createAvatar(context), returning an Object3D plus update(pose, dt, settings), reset(), and dispose(). Its manifest declares a name, defaults, and behavior fields. The template generates the picker and sliders and stores a separate preset for every avatar.
Start by copying rectangle.mjs, register a loader and manifest entry, then map the shared pose to your own character. See the complete module guide. This is an extensible code template, not automatic rigging or a universal VRM importer. Your module supplies the behavior and rig mapping.
Inputs #
| Xbox input | Motion |
|---|---|
| Left stick | Head yaw and pitch |
| Right stick | Eye gaze |
| LT / RT | Head roll |
| A | Blink both eyes |
| LB / RB | Wink |
| Y / Menu | Reset pose / camera |
Spring mode returns to neutral; Hold retains the steered pose. On Windows, a hidden PowerShell XInput helper keeps working outside browser/OBS focus without changing execution policy. Manual sliders pause it; choose Xbox controller to resume. Browser fallback requires browser gamepad support and interaction.
The included SwiftUI iPhone sender uses ARKit for head orientation, combined eye direction and independent blinks. Build ios/GhostFace.xcodeproj on a Mac with compatible Xcode, select your own signing team, and run on a supported physical phone. See installation.
Put phone and computer on the same LAN. Enter a desktop IPv4 address shown in the tester, start tracking, look forward with eyes open, and Center. Only pose numbers leave the phone; camera frames stay there. There is no tracking account or subscription.
HTTP stays on loopback 8766; the phone receiver uses LAN UDP 49984. Review setup-phone-firewall.ps1 before running it as Administrator on Windows: it permits the resolved Node executable and this port from LocalSubnet on Private/Public profiles. Rerun after changing Node installations. UDP is unauthenticated and unencrypted; use a trusted LAN and do not forward the port on a router.
Tune and save #
Open http://127.0.0.1:8766/?settings=1.
- Avatar behavior changes with the selected avatar. Rectangle has follow delay, bounded eye travel and movement squash. Ghost has hat and pom/ornament physics.
- Save avatar remembers selection and behavior presets in data/avatar-settings.json. Revert/default actions affect the visible avatar's behavior.
- Tracking settings control shared head/eye gains, smoothing and direction. Save settings writes data/tracking-settings.json.
- The hosted demo saves both categories in that browser instead. No public tracking API is exposed.
- Centering is temporary. Higher gains expand travel; each adapter decides how to bound its geometry.
The ghost keeps its original pom defaults: 56° range, 15 stiffness, 13.25 damping, 8% soft-edge start, and 3.3× gravity. Existing saved ghost tuning is migrated into its avatar preset on first local use.
OBS #
- Keep the local server running.
- Add a Browser Source, Local file off, using http://127.0.0.1:8766/?output=1.
- Try 1080 × 1080 at 60 FPS and leave OBS's transparent CSS intact.
The source follows the shared local avatar selection and pose. Add &avatar=rectangle or &avatar=ghost to pin a source to one avatar; the tester's OBS output link pins the visible choice. The alpha canvas hides UI/background/floor, so no green screen is needed. Refresh OBS after code changes.
Learn and develop #
- Avatar modules: interface, registration, settings, lifecycle and examples.
- Walkthrough: tracking and the original ghost's deformation/physics/rendering.
- Ghost rig contract: its specialized bones, eyes and material mapping.
- Protocol: write another tracking sender.
- Blender: source and recipes for the ghost example.
- Contributing: source map, tests and limits.
Run node scripts/test.mjs for all tests. For formatting only, npm ci then npm run format:check or npm run format. Tests do not replace physical iPhone, GPU or OBS verification.
License #
Original code, documentation and procedural rectangle: MIT. Ghost assets: CC BY 4.0, credit cee.wtf. Three.js and its add-ons retain their MIT notice. Third-party notices.