Skip to content

Instantly share code, notes, and snippets.

@8ullyMaguire
Last active June 12, 2026 20:31
Show Gist options
  • Select an option

  • Save 8ullyMaguire/8425b33dc74be9abcf52f9f3d1cbc46a to your computer and use it in GitHub Desktop.

Select an option

Save 8ullyMaguire/8425b33dc74be9abcf52f9f3d1cbc46a to your computer and use it in GitHub Desktop.
VTuber Setup Log — XR Animator + Warudo + OBS on Linux

VTuber Setup Log — XR Animator + Warudo + OBS on Linux

Date: 2026-06-12 System: Linux, Cinnamon DE User: $HOME

Table of Contents

  1. Overview
  2. XR Animator — Install & Move to Permanent Location
  3. Launch Script — ~/bin/xr-animator
  4. App Launcher — Manjaro Menu Entry
  5. VMC Protocol & Warudo Integration
  6. OBS Integration — Window Capture + Transparent BG
  7. AI VTuber Daemon (Hermes Agent)
  8. Quick Start / Calibration
  9. Pitfalls & Notes
  10. VSeeFace — Install & Setup (Wine via GE-Proton)
  11. Skill Creation Instructions
  12. Troubleshooting — Warudo & VSeeFace on Linux
  13. Manjaro VTuber Guide — VTube Studio + FaceTracker

1. Overview

Component What Location
XR Animator Electron-based VRM/MMD avatar face+body tracking via webcam ~/.local/opt/xr-animator/
Launcher Shell script with --bg flag ~/bin/xr-animator (in PATH)
Desktop entry Manjaro app menu launcher ~/.local/share/applications/xr-animator.desktop
VMC accessories Warudo & VNyan VMC camera integrations ~/.local/opt/xr-animator/accessories/
ffmpeg Static build bundled for video/image -> 3D backdrop conversion ~/.local/opt/xr-animator/accessories/ffmpeg/
VRM model Avatar file, loaded in-app ~/.local/opt/xr-animator/avatar.glb
App version v0.34.0 (electron-v35.1.2) GitHub: https://github.com/ButzYung/SystemAnimatorOnline
Webcam Required for tracking (face, body, hands)
OBS integration Window Capture with transparent background Scene: Scene 1 or custom VTuber scene

VMC protocol ports (UDP):

  • 39539 — XR Animator → Warudo/VNyan (send)
  • 39540–39543 — XR Animator VMC receiver slots (optional, for receiving mocap from other apps)

2. XR Animator — Install & Move to Permanent Location

Original location (temp)

~/downloads/XR-Animator/

Permanent location

~/.local/opt/xr-animator/

Steps performed

  1. Copied with cp -a — preserves symlinks, permissions, etc.
  2. Fixed permissions — the bundled .gadget dir contains many chmod r-x directories (all files owned user:user but dirs missing write bit). Ran chmod -R u+w ~/.local/opt/xr-animator/ to allow deletions and writes.
  3. Cleaned nested duplicate — The original ~/downloads/XR-Animator/ had a nested XR-Animator/ subdirectory (double-extraction artifact). Removed after move.
  4. Removed from Downloads with rm -rf after permission fixes.

Directory structure after final move

~/.local/opt/xr-animator/
├── accessories/
│   ├── ffmpeg/                    ← Static ffmpeg 7.0.2 for video→3D backdrop
│   ├── VNyan - VMC camera/       ← VNyan VMC camera prop file
│   └── Warudo - VMC camera/      ← VMC Camera.json blueprint for Warudo
├── AT_SystemAnimator_v110340.gadget/  ← The actual app (NW.js gadget)
│   ├── TEMP/_config_local/XR Animator.js  ← Saved settings (auto-created on first run)
│   └── ...
├── avatar.glb                    ← VRM model (downloaded from VRoid Hub, ID: REDACTED)
├── readme.txt                    ← Original app readme
└── session-summary.md            ← Updated setup notes

App binary

~/.local/opt/xr-animator/XR Animator - electron-v35.1.2-linux-x64_SA/electron

Settings persistence

XR Animator writes its settings to:

~/.local/opt/xr-animator/AT_SystemAnimator_v110340.gadget/TEMP/_config_local/XR Animator.js

Crucially, the config file still references the old path on first launch after move:

System.Gadget.path = "$HOME/downloads/XR-Animator/AT_SystemAnimator_v110340.gadget"

After moving, on next launch the app should auto-update this path since it runs from the new CWD. If it fails to load, edit XR Animator.js and replace the old path string with the new one.

Icon

Best icon for .desktop file:

~/.local/opt/xr-animator/AT_SystemAnimator_v110340.gadget/icon_SA_512x512.png

3. Launch Script — ~/bin/xr-animator

File: $HOME/bin/xr-animator Permissions: chmod +x (755) 25 lines.

Behaviour

Command Action
xr-animator Launch in foreground (terminal blocks)
xr-animator --bg or -b Launch in background, logs to /tmp/xr-animator.log, shows notify-send with PID

Key logic

  1. cd to ~/.local/opt/xr-animator/ — the app looks for AT_SystemAnimator_v110340.gadget relative to CWD
  2. Validates the electron binary exists and is executable
  3. Launches it (foreground or background based on --bg)
  4. Error notifications via notify-send if dir/binary missing

Script content

#!/usr/bin/env bash
DIR="$HOME/.local/opt/xr-animator"
ELECTRON="$DIR/XR Animator - electron-v35.1.2-linux-x64_SA/electron"
LOG="/tmp/xr-animator.log"

cd "$DIR" || { notify-send -t 3000 "XR Animator" "Directory not found: $DIR"; exit 1; }
[ ! -x "$ELECTRON" ] && { notify-send -t 3000 "XR Animator" "Binary not found"; exit 1; }

if [ "$1" = "--bg" ] || [ "$1" = "-b" ]; then
    "$ELECTRON" &>"$LOG" &
    disown
    notify-send -t 1500 "XR Animator" "Launched in background (PID $!)"
else
    "$ELECTRON"
fi

PATH

~/bin/ is already in $PATH (set by .zshenv or system profile). No additional PATH modification needed.


4. App Launcher — Manjaro Menu Entry

File: ~/.local/share/applications/xr-animator.desktop

[Desktop Entry]
Type=Application
Name=XR Animator
Comment=VRM/MMD avatar face & body tracking animation app
Exec=$HOME/bin/xr-animator
Icon=$HOME/.local/opt/xr-animator/AT_SystemAnimator_v110340.gadget/icon_SA_512x512.png
Terminal=false
Categories=Graphics;
StartupNotify=true
StartupWMClass=XR Animator

Notes

  • Only Graphics; as the category (no 3D; — not a registered Freedesktop category, causes desktop-file-validate hint)
  • StartupWMClass=XR Animator for Cinnamon window grouping
  • No terminal wrapper needed since the script handles both foreground/background
  • App shows in Manjaro menu under "Graphics" category
  • Run update-desktop-database ~/.local/share/applications/ after creating the file (menu picks it up on next login even without it)

5. VMC Protocol & Warudo Integration

How VMC works

VMC (Virtual Motion Capture) is a UDP-based protocol for sending avatar tracking data between apps. XR Animator can:

  • Send — transmit face/pose/hand tracking data + camera data to Warudo, VNyan, or any VMC-compatible app
  • Receive — accept mocap data from other VMC senders on ports 39540–39543

Warudo Integration

Warudo is a 3D VTuber app (primarily Windows, can run on Linux via Steam Play/Proton). VMC camera is not supported by default in Warudo.

Warudo setup steps (from accessories/Warudo - VMC camera/readme.txt):

  1. Install OS C Input Node from Steam Workshop:

  2. Import blueprint: VMC Camera.json

    • Located at: ~/.local/opt/xr-animator/accessories/Warudo - VMC camera/VMC Camera.json
    • Import into Warudo as a blueprint
  3. Select avatar — preferably the same VRM model as used in XR Animator

  4. Configure VMC Receiver in Warudo:

    • Set port to 39539 (XR Animator's send port)
    • Use VMC for both face and pose tracking
  5. XR Animator side:

    • Double-click "VMC-protocol" in the UI
    • Set "App mode" to "Warudo"
    • Set "VMC-protocol" to ON
    • Set "Send camera data" to ON (if you want 3D camera movement)
  6. Firewall: Allow both XR Animator and Warudo on the network if prompted

Warudo smoothness tuning (for less latency):

  • Open these blueprints: "Face Tracking - VMC", "Pose Tracking - VMC", "VMC Camera", "VMC Trackers"
  • Reduce "Smooth Time" on nodes: Smooth Blendshape List, Smooth Position List, Smooth Rotation List, Smooth Transform → around 0.2
  • To prevent Warudo overriding head rotation: open "Face Tracking - VMC" blueprint → set "Character Look At Target" → Enabled: No

VNyan Integration (alternative to Warudo)

VNyan is another VTuber app (Windows, Proton-compatible).

VNyan setup steps (from accessories/VNyan - VMC camera/readme.txt):

  1. Select avatar in VNyan (same VRM model as XR Animator)
  2. Props → Add Prop → select VMC_camera_for_VNyan.vnprop
    • Located at: ~/.local/opt/xr-animator/accessories/VNyan - VMC camera/VMC_camera_for_VNyan.vnprop
  3. Choose "Tracker 1" as "Linked Bone"
  4. Settings → General settings → VMC Receiver → port: 39539
  5. VMC Tracker Mapping → select tracker slot → enter "Camera" as name
  6. Same XR Animator side steps (VMC-protocol ON, App mode: "VNyan", Send camera data: ON)

VMC Port Summary

Port Direction Purpose
39539 XR Animator → External Send tracking data (face, pose, hands, camera)
39540 External → XR Animator Receive slot 1 (optional)
39541 External → XR Animator Receive slot 2 (optional)
39542 External → XR Animator Receive slot 3 (optional)
39543 External → XR Animator Receive slot 4 (optional)

Current XR Animator VMC Config (from saved settings)

VMC: {
  send: {
    port: 39539,
    host: "localhost"
  },
  delay: 0,
  VMC_receiver: {
    config: { prop_mocap_factor_percent: 50 },
    receiver_config: [
      { enabled: false, port: 39540, port_default: 39540, face: 0, pose: 0, hand: 0 },
      { enabled: false, port: 39541, ... },
      { enabled: false, port: 39542, ... },
      { enabled: false, port: 39543, ... },
    ]
  }
}

All receiver slots currently disabled — only sending on port 39539.


6. OBS Integration — Window Capture + Transparent BG

Adding XR Animator to OBS

  1. In XR Animator: enable Transparent background (UI checkbox)
  2. In OBS: add a Window Capture (Xcomposite) source
  3. Select the "XR Animator" window
  4. Position/size as desired in your scene

The transparent background makes only the avatar render, enabling overlay-style compositing.

Current OBS setup on this machine

This Manjaro system has:

  • OBS version: 32.1.2-5
  • Profile: streamer
  • Scene collection: Untitled
  • Current scene: Scene 1
  • WebSocket: port 4455, password REDACTED
  • Scenes: only "Scene 1" (no dedicated VTuber/AI VTuber scene on this machine yet)
  • Video: 1919×1079 base, 1280×720 output, 30 fps
  • Audio: TONOR TC-777 (USB) via Mic/Aux, unmuted, toggled via Ctrl+Shift+M
  • Mic filter chain: Noise Suppression (RNNoise) → Gain (+8 dB) → Noise Gate (open -26, close -36) → Compressor (6:1) → Limiter (-3 dB)

For a dedicated VTuber scene, create a new scene "VTuber Overlay" in OBS:

  • Add XR Animator as a Window Capture source
  • Add Twitch Chat (browser source with transparent CSS)
  • Optionally add game capture sources beneath the avatar

OBS integration documentation (from session-summary.md)

Original notes (preserved for skill context):

- Add Window Capture (Xcomposite) source → select "XR Animator" window
- With transparent background enabled, only the avatar overlays

7. AI VTuber Daemon (Hermes Agent)

Previous setup (on different machine L480) used a Hermes AI VTuber daemon at ~/.hermes/ai_vtuber/ with:

  • AI VTuber Avatar — browser source at http://localhost:8888/avatar (600×700)
  • AI VTuber Chat — Twitch popout browser source (380×600)
  • AI VTuber Game — browser source at http://localhost:8888/snake.html (400×400)
  • TTS: edge-tts AndrewNeural
  • Python venv: /tmp/vtuber_venv/ with simpleobsws
  • OBS WebSocket control via Hermes agent

Not currently set up on this Manjaro system — documented here for future skill creation.


8. Quick Start / Calibration

When running XR Animator for the first time:

  1. Launch: xr-animator or xr-animator --bg
  2. Fontconfig warnings on first launch are harmless
  3. Load VRM model: click "VRM/MMD Model" button → navigate to ~/.local/opt/xr-animator/avatar.glb
  4. Select webcam: go to "Camera & Mic" tab → choose your capture device
  5. Enable tracking: check Face Tracking, Body Tracking (optionally Hand Tracking)
  6. Enable transparent background: for OBS capture overlay
  7. Calibrate: stand in neutral pose (T-pose/A-pose) in full webcam view, good lighting
  8. Enable VMC (optional): double-click "VMC-protocol" → set App Mode → turn ON

Settings for best streaming quality

From current saved config:

  • Face/body ML model inference: CPU (not GPU)
  • Mocap data smoothing: level 2 (moderate)
  • Auto blink: off (uses webcam blink detection)
  • Eye tracking: on
  • Mouth tracking sensitivity: 1.0
  • Head stabilization: enabled
  • Arm IK: disabled (uses raw tracking by default)

9. Pitfalls & Notes

File permissions

The bundled .gadget directory has many dr-xr-xr-x directories (no write bit on the directory entry). After cp -a, you must run:

chmod -R u+w ~/.local/opt/xr-animator/

Otherwise rm, mv, and the app's own settings save will fail.

CWD requirement

XR Animator must be launched from its own directory — it resolves AT_SystemAnimator_v110340.gadget relative to CWD. The launch script handles this with cd "$DIR" before executing electron.

Config path update after move

After moving XR Animator, the saved config at TEMP/_config_local/XR Animator.js still contains the old absolute path:

System.Gadget.path = "$HOME/downloads/XR-Animator/AT_SystemAnimator_v110340.gadget"

Edit this file to update the path if the app fails to load after a move. It should auto-update on next launch since the CWD changed.

VMC on Manjaro / Linux

Warudo and VNyan are Windows-native apps. On Linux:

  • Warudo: may work via Steam Play (Proton) — requires Steam client and Workshop access for the OSC plugin
  • VNyan: may work via Wine/Proton (Itch.io download)
  • Firewall: VMC uses UDP, ensure port 39539 is open on the host firewall if apps are on different machines

Bundled ffmpeg

Bundled ffmpeg 7.0.2 (glibc static) lives in accessories/ffmpeg/. It's used by XR Animator for converting video files into 3D depth-mapped backdrops. The system ffmpeg package is also available via pamac but the bundled one is the one the app expects.

Electron window transparent behaviour

XR Animator uses "transparent": true in its package.json for the transparent background feature. This works reliably on X11 (Xcomposite) but may have issues on Wayland.

Memory/Resources

XR Animator with face+body tracking uses ~200–400MB RAM. The bundled electron binary is ~194MB on disk. Webcam + ML inference adds CPU load — expect 20-40% on a modern CPU.


10. VSeeFace — Install & Setup (Wine via GE-Proton)

Overview

Item Value
App VSeeFace — Windows Unity VRM/MMD avatar face tracking & VTuber app
Version v1.13.38c4
Location ~/.local/opt/vseeface/VSeeFace/
Wine runner GE-Proton10-34 (Lutris runner, managed by ProtonUp-QT)
Wine prefix ~/.local/share/vseeface/prefix (64-bit)
Launcher script ~/bin/vseeface (in PATH)
App launcher Manjaro menu → "VSeeFace"
Download URL https://github.com/emilianavt/VSeeFaceReleases/releases/download/v1.13.38c/VSeeFace-v1.13.38c4.zip
Website https://www.vseeface.icu
Repository https://github.com/emilianavt/VSeeFaceReleases

Approach

VSeeFace is a Windows-native Unity app. It is run on Linux via Wine (specifically the GE-Proton fork, which has patches for media foundation, font rendering, and Unity compatibility). The setup uses:

  • ProtonUp-QT — to manage GE-Proton runner versions (already installed: protonup-qt 2.15.0)
  • Lutris — to manage the Wine prefix and per-app runner configuration (installed via pamac)
  • winetricks — to install corefonts (prevents invisible text in the app)

Step-by-step setup

10.1 Install dependencies

pamac install lutris winetricks

10.2 Install a GE-Proton Lutris Wine runner

Open ProtonUp-QT → select Lutris → install GE-Proton (e.g., v10.34). This places the runner at:

~/.local/share/lutris/runners/wine/GE-Proton10-34/

The Wine binary is at:

~/.local/share/lutris/runners/wine/GE-Proton10-34/files/bin/wine

10.3 Download & extract VSeeFace

# Download
wget -O ~/Downloads/VSeeFace.zip https://github.com/emilianavt/VSeeFaceReleases/releases/download/v1.13.38c/VSeeFace-v1.13.38c4.zip

# Extract to permanent location
mkdir -p ~/.local/opt/vseeface/
unzip ~/Downloads/VSeeFace.zip -d ~/.local/opt/vseeface/

Result:

~/.local/opt/vseeface/VSeeFace/
├── MonoBleedingEdge/       ← Mono runtime for Unity
├── Release notes.txt
├── UnityCrashHandler64.exe
├── UnityPlayer.dll
├── VSeeFace.exe            ← Main executable (650KB)
└── VSeeFace_Data/          ← Unity assets, models, strings

10.4 Create Wine prefix & install fonts

export WINEPREFIX="$HOME/.local/share/vseeface/prefix"
export WINE="$HOME/.local/share/lutris/runners/wine/GE-Proton10-34/files/bin/wine"

# Install corefonts (prevents invisible text in Unity UI)
winetricks corefonts

First run creates the prefix (64-bit by default). Ignore any Wine debug warnings.

10.5 Create game entry in Lutris GUI (required)

A YAML file alone in ~/.config/lutris/games/ does not register the game — Lutris needs an entry in its internal SQLite database. Create it through the GUI:

  1. Open Lutris (from app menu or lutris in terminal)

  2. Click + (Add game) → Add locally installed game

  3. Fill in the form:

    Field Value
    Name VSeeFace
    Runner Wine
    Game → Executable Browse to ~/.local/opt/vseeface/VSeeFace/VSeeFace.exe

| Game → Arguments | --background-color '#00FF00' (green screen) | | Game → Working directory | ~/.local/opt/vseeface (parent dir, not VSeeFace/) | | Game → Wine prefix | ~/.local/share/vseeface/prefix | | Wine → Wine version | Select GE-Proton10-34 (must already be installed via ProtonUp-QT) | | Wine → DXVK/VKD3D | Off (not needed for this app) | | Wine → Esync | On |

  1. Click Save

The game entry is now stored in Lutris's database and will appear in the library. To launch from Lutris: double-click it, or right-click → Run.

Alternative — CLI install from a YAML file:

lutris --install ~/.config/lutris/games/vseeface.yml

This works if the YAML is a proper Lutris installer script (different format from a game config). The YAML file format placed manually in ~/.config/lutris/games/ is a runtime config, not a bootstrap — Lutris does not auto-detect it. The actual config is written by the GUI after registering the game.

For reference, the runtime config written by Lutris after manual setup is saved under a slug‑based filename:

# ~/.config/lutris/games/vseeface-{timestamp}.yml
# (auto-generated by Lutris GUI — example below)
game:
  args: --background-color '#00FF00'
  exe: $HOME/.local/opt/vseeface/VSeeFace/VSeeFace.exe
  prefix: $HOME/.local/share/vseeface/prefix
  working_dir: $HOME/.local/opt/vseeface

10.6 Launcher script — ~/bin/vseeface

File: $HOME/bin/vseeface Permissions: chmod +x (755)

#!/usr/bin/env bash
VSF_DIR="$HOME/.local/opt/vseeface"
WINEPREFIX="$HOME/.local/share/vseeface/prefix"
WINE="$HOME/.local/share/lutris/runners/wine/GE-Proton10-34/files/bin/wine"
LOG="/tmp/vseeface.log"
EXE="$VSF_DIR/VSeeFace/VSeeFace.exe"

cd "$VSF_DIR" || exit 1
[ ! -x "$WINE" ] && { notify-send -t 3000 "VSeeFace" "GE-Proton Wine not found"; exit 1; }
[ ! -f "$EXE" ] && { notify-send -t 3000 "VSeeFace" "VSeeFace.exe not found"; exit 1; }

export WINEPREFIX
export DXVK_ENABLE_NVAPI=0
export __GL_SHADER_DISK_CACHE=1
export __GL_SHADER_DISK_CACHE_SIZE=1073741824

if [ "$1" = "--bg" ] || [ "$1" = "-b" ]; then
    "$WINE" "$EXE" --background-color '#00FF00' &>"$LOG" &
    disown
    notify-send -t 1500 "VSeeFace" "Launched in background (PID $!)"
else
    "$WINE" "$EXE" --background-color '#00FF00'
fi

10.7 Desktop entry

File: ~/.local/share/applications/vseeface.desktop

[Desktop Entry]
Type=Application
Name=VSeeFace
Comment=VRM/MMD avatar face tracking & VTuber app (Wine)
Exec=$HOME/bin/vseeface
Icon=$HOME/.local/opt/vseeface/VSeeFace/VSeeFace_Data/StreamingAssets/Transparent.png
Terminal=false
Categories=Graphics;
StartupNotify=true
StartupWMClass=VSeeFace.exe

(The icon is a transparent PNG used for chroma key; replace with a proper app icon if desired.)

10.8 First-run & configuration

  1. Launch: vseeface or vseeface --bg
  2. Add VRM model — browse to your .vrm file (e.g., ~/.local/opt/xr-animator/avatar.glb)
  3. Camera: select any option (webcam not used for tracking in this setup)
  4. Microphone: select e.g., "OBS Source" or your mic
  5. Settings → General:
    • Enable OSC/VMC Receiver
    • Enable Track Face Features (for lip sync; note this disables facial expressions)
  6. Chroma key: the --background-color '#00FF00' argument makes the background green
  7. In OBS: add Window Capture → select VSeeFace → add Chroma Key filter → key out green (#00FF00)

10.9 Integration with XR Animator (VMC pipeline)

VSeeFace receives tracking data from XR Animator via VMC protocol:

  1. XR Animator side: double-click "VMC-protocol" → App mode: "Others" → ON → Enable "Send camera data"
  2. VSeeFace side: Settings → General → OSC/VMC Receiver → ON (listens on port 39540 by default)
  3. XR Animator sends on port 39539 → VSeeFace receives and applies tracking to the avatar

10.10 Known issues

  • Fonts: if text is invisible in VSeeFace, run winetricks corefonts again
  • Camera access: Wine/Proton cannot directly access webcams — use XR Animator (native Linux) for tracking and send via VMC
  • Performance: GE-Proton with esync=true reduces CPU overhead vs system Wine
  • Chroma key color: #00FF00 (green) — standard green screen. Magenta (ff00ff) is also possible if you need to avoid green for assets.

11. Skill Creation Instructions

Purpose

Create a Hermes Agent skill that can autonomously set up the full VTuber pipeline (XR Animator + VSeeFace + OBS) on a fresh Linux system.

Skill structure

skills/vtubing-setup/
├── SKILL.md                          # Main instructions
├── references/
│   ├── xr-animator-setup.md          ← Detailed XR Animator steps (from §2-4)
│   ├── vseeface-wine-setup.md        ← Detailed VSeeFace + Wine steps (from §10)
│   ├── vmc-protocol-config.md        ← VMC port table & config (from §5)
│   └── obs-vtuber-scene.md           ← OBS scene setup (from §6)
├── scripts/
│   ├── install-vseeface.sh           ← Download + extract VSeeFace
│   ├── install-xr-animator.sh        ← Download + extract XR Animator
│   └── fix-v4l2loopback.sh           ← Blacklist v4l2loopback if needed
└── templates/
    ├── vseeface.desktop              ← Template .desktop file
    └── xr-animator.desktop           ← Template .desktop file

Automated download script for VSeeFace

The AI agent should use this to download VSeeFace programmatically (no manual browser):

#!/usr/bin/env bash
# install-vseeface.sh — download & extract VSeeFace
set -euo pipefail

VSF_VERSION="v1.13.38c4"
VSF_URL="https://github.com/emilianavt/VSeeFaceReleases/releases/download/v1.13.38c/VSeeFace-v1.13.38c4.zip"
VSF_DEST="$HOME/.local/opt/vseeface"
ZIP_PATH="/tmp/VSeeFace.zip"

echo "Downloading VSeeFace ${VSF_VERSION}..."
wget -q --show-progress -O "$ZIP_PATH" "$VSF_URL"

echo "Extracting to $VSF_DEST..."
mkdir -p "$VSF_DEST"
unzip -q "$ZIP_PATH" -d "$VSF_DEST"
rm -f "$ZIP_PATH"

echo "VSeeFace installed at $VSF_DEST/VSeeFace/"

Automated download script for XR Animator (Linux)

#!/usr/bin/env bash
# install-xr-animator.sh — download & extract XR Animator Linux
set -euo pipefail

# Check latest release from GitHub
LATEST=$(curl -s https://api.github.com/repos/ButzYung/SystemAnimatorOnline/releases/latest \
    | python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'])")

# The Linux release tarball naming convention may vary; check the releases page
# for the actual format: XrAnimator-Linux64-<version>.tar.gz
RELEASE_URL="https://github.com/ButzYung/SystemAnimatorOnline/releases/download/${LATEST}/XrAnimator-Linux64-${LATEST}.tar.gz"
DEST="$HOME/.local/opt/xr-animator"
TARBALL="/tmp/xr-animator.tar.gz"

echo "Downloading XR Animator ${LATEST}..."
wget -q --show-progress -O "$TARBALL" "$RELEASE_URL" || {
    echo "ERROR: Could not download. Check https://github.com/ButzYung/SystemAnimatorOnline/releases"
    exit 1
}

echo "Extracting to $DEST..."
mkdir -p "$DEST"
tar xzf "$TARBALL" -C "$DEST" --strip-components=1
rm -f "$TARBALL"

# Fix permissions (the .gadget dir has read-only directories)
chmod -R u+w "$DEST"
echo "XR Animator installed at $DEST"

Skill SKILL.md template

The skill should include:

# vtubing-setup — Full VTuber Pipeline on Linux

Sets up XR Animator (native Linux tracking) + VSeeFace (Wine VRM avatar) + OBS
on Manjaro (or any Arch-based) Linux.

## Prerequisites

- Arch-based Linux with pacman
- Webcam (e.g., NexiGo N60) with working uvcvideo driver
- OBS Studio installed (`pamac install obs-studio obs-cmd`)
- Internet connection for downloads

## Trigger conditions

User asks: "set up vtubing" or "configure vseeface" or "install xr animator"

## Steps

1. **Check prerequisites:**
   - Verify `/dev/video*` has a real webcam (not v4l2loopback)
   - If v4l2loopback is loaded: `sudo modprobe -r v4l2loopback` and blacklist
   - Install packages: `pamac install wine lutris winetricks`

2. **Install GE-Proton runner via ProtonUp-QT:**
   - Run: `protonup-qt` (GUI)
   - Select Lutris → install latest GE-Proton version

3. **Download & install XR Animator** (from GitHub releases)

4. **Set up XR Animator:**
   - Create `~/bin/xr-animator` launcher
   - Create `.desktop` entry at `~/.local/share/applications/`
   - Make executable

5. **Download & install VSeeFace** (from GitHub releases ZIP)

6. **Create Wine prefix & install fonts:**
   ```bash
   WINEPREFIX=~/.local/share/vseeface/prefix \
   WINE=~/.local/share/lutris/runners/wine/GE-Proton*/files/bin/wine \
   winetricks corefonts
  1. Create ~/bin/vseeface launcher script (see vseeface-wine-setup.md)

  2. Create .desktop entry for VSeeFace

  3. Configure VMC protocol:

    • XR Animator: VMC ON, port 39539, App mode: Others, Send camera ON
    • VSeeFace: Settings → OSC/VMC Receiver → ON
  4. Configure OBS:

    • Add XR Animator as Window Capture (transparent BG)
    • Add VSeeFace as Window Capture + Chroma Key (green #00FF00)

Verification

  • ls /dev/video* shows webcam
  • xr-animator launches and tracks face/body
  • vseeface launches (may take 30s first time)
  • Avatar in VSeeFace mirrors XR Animator tracking

Pitfalls

  • v4l2loopback breaks webcam detection — always blacklist if not needed
  • VSeeFace first run can take 30–60s (Mono JIT compilation)
  • GE-Proton 10.x recommended; some older VSeeFace versions need GE-Proton 8.x
  • Wine cannot access webcams natively — always use XR Animator as tracking source
---

*Updated: 2026-06-12 — Added VSeeFace section + skill creation instructions*

---

## 12. Troubleshooting — Warudo & VSeeFace on Linux

### Warudo — Error -36861 (crash on launch)

**Symptom:** Warudo crashes immediately on launch with `Error code -36861` and a misleading Windows message about reinstalling on the system drive. This is a **Proton compatibility issue**, not a broken install.

**Root cause:** Warudo has a compatibility problem with Proton 9.x and newer GE-Proton versions. The app crashes on launch when using anything newer than Proton 8.0-5.

**Fix** (tested on Manjaro with Nvidia GPU):

1. In Steam library → right-click Warudo → **Properties → Compatibility**
2. Check **"Force the use of a specific Steam Play compatibility tool"**
3. Select **Proton 8.0-5** from the dropdown (not 9.x, not GE-Proton)
4. In **Launch Options**, add:
   ```bash
   PROTON_DISABLE_NVAPI=1 %command%

Disabling NVAPI prevents Warudo from trying to use an unsupported DLSS feature. 5. Launch Warudo again

If the issue persists:

  • Add PROTON_USE_WOW64=1 alongside PROTON_DISABLE_NVAPI=1
  • Verify integrity of game files in Steam (Properties → Installed Files)
  • Ensure the Steam library folder is owned by your Linux user (not root)

Note: Solution applies to Manjaro, Arch, and most Linux distros. Check ProtonDB and Warudo Steam community hub for updates — Proton compatibility changes with new releases.

VSeeFace — Not working

VSeeFace (Windows Unity app via Wine/GE-Proton) may also fail to work properly on Linux. Known issues:

  • Camera access: Wine/Proton cannot directly access webcams natively
  • Unity/Mono rendering issues under Wine (varies by GPU driver and Wine version)
  • Chroma key transparency may not render correctly

Fallback approach: If neither VSeeFace nor Warudo work, the remaining pipeline is:

  1. XR Animator (native Linux) — handles face/body tracking via webcam
  2. OBS — composite the scene directly with XR Animator's transparent background Window Capture
  3. AI VTuber daemon (Hermes Agent / browser-based avatar) as an alternative avatar renderer

Current Pipeline (Working)

Component Status Notes
NexiGo N60 webcam Working Detected at /dev/video0 after v4l2loopback blacklist
XR Animator Working Native Linux Electron app, face/body/hand tracking
OBS Working Window Capture + transparent BG for XR Animator
VMC protocol Configured XR Animator sends on port 39539
VSeeFace ❌ Not working Wine/Proton rendering issues
Warudo ❌ Not working Error -36861, needs Proton 8.0-5 (not tested)

End of VTuber setup log — 2026-06-12


13. Manjaro VTuber Guide — VTube Studio + FaceTracker (Working Pipeline)

This section documents the working VTuber pipeline based on the KyloNeko Linux Guide to Vtubing and the VTube Studio on Linux wiki. It uses FaceTracker (flatpak GUI wrapper for OpenSeeFace) sending tracking data via UDP to VTube Studio (Steam/Proton).

Unlike the XR Animator + VSeeFace/Warudo pipeline (which had Wine/Proton compatibility issues), this setup works on Manjaro with 2D Live2D avatars.

13.1 Overview

Component Role Install Method
NexiGo N60 webcam Video input USB, UVC driver built-in
FaceTracker OpenSeeFace tracking via webcam Flatpak (de.z_ray.Facetracker)
VTube Studio Live2D avatar display & puppeteering Steam (Proton / GE-Proton)
OBS Scene compositing & streaming Native (pamac install obs-studio)

13.2 Prerequisites

Manjaro with:

  • Webcam working (ls /dev/video* shows devices)
  • v4l2loopback blacklisted (see §2.5) — or webcam won't be detected
  • Flatpak support enabled (pamac install flatpak if not present)
  • Steam installed (pamac install steam)

13.3 Install FaceTracker (flatpak)

flatpak install flathub de.z_ray.Facetracker

FaceTracker is a GTK4 GUI wrapper around the OpenSeeFace Python tracker. It:

  • Lists available webcams
  • Lets you select tracking model quality (0-4, default 3)
  • Sends tracking data via UDP to a configurable IP and port
  • Default: 0.0.0.0 (all interfaces) on port 11573

13.4 Configure VTube Studio

VTube Studio ip.txt:

File location: ~/.local/share/Steam/steamapps/common/VTube Studio/VTube Studio_Data/StreamingAssets/ip.txt

Must contain exactly:

ip=0.0.0.0
port=11573

This tells VTS to listen for incoming tracking data on all network interfaces, port 11573.

VTube Studio Steam launch options (optional):

If using GE-Proton (e.g., GE-Proton10-34), no special launch options are needed for basic tracking. If using Proton Experimental or stock Proton, add:

PROTON_DISABLE_NVAPI=1 %command%

Compatibility: GE-Proton10-34 is confirmed working.

13.5 Step-by-step: Launch & Connect

Step 1 — Launch FaceTracker

flatpak run de.z_ray.Facetracker

Or launch from the app menu ("Facetracker" under Utilities).

Step 2 — Configure FaceTracker

In the FaceTracker GUI:

  1. Camera dropdown — select your webcam (e.g., "NexiGo N60 FHD Webcam")
  2. Resolution — 1280×720 or 640×480 (higher = more CPU, better tracking)
  3. FPS — 30 (default)
  4. Tracking Model3: Default (good balance of quality and speed)
  5. IP Address0.0.0.0 (send to localhost)
  6. Port11573 (must match VTube Studio's ip.txt)

Step 3 — Start tracking

Click the camera icon button in the header bar. The button turns red (destructive-action style) when tracking is active. A terminal window may briefly flash — this is the OpenSeeFace Python process launching.

Step 4 — Launch VTube Studio

Launch VTube Studio from Steam. Wait for it to fully load and show the model selector.

Step 5 — Select tracking input

  1. In VTube Studio, go to Settings → Tracking
  2. Under Tracking Input, select VTubeStudioCam
  3. (Optional) Click Calibrate and follow the on-screen instructions

Step 6 — Verify tracking

Your avatar's face should now mirror your movements. If not:

  • Check the FaceTracker window — is it showing a camera feed preview?
  • Check VTS settings → Tracking Input → is "VTubeStudioCam" selected?
  • Check the IP/port in both apps match exactly

13.6 Troubleshooting — No Face Tracking

Symptom: "I don't see any face tracking on VTube Studio"

Most common causes and fixes, in order:

1. FaceTracker not running

  • Launch FaceTracker from app menu or flatpak run de.z_ray.Facetracker
  • Click the camera button in the header bar (turns red when active)
  • Verify webcam is selected in the dropdown

2. Wrong tracking input in VTube Studio

  • Settings → Tracking → Tracking Input must be set to "VTubeStudioCam"
  • NOT "OpenSeeFace" (that expects a different protocol)
  • NOT "iPhone" or "iFacialMocap"

3. IP/port mismatch

App Setting Must Be
FaceTracker IP Address 0.0.0.0
FaceTracker Port 11573
VTS ip.txt ip= 0.0.0.0
VTS ip.txt port= 11573

If either is wrong, no data reaches VTS.

4. Firewall blocking UDP

  • FaceTracker sends UDP packets to port 11573
  • Check with: ss -ulpn | grep 11573 (VTS should be listening)

5. Webcam busy or capture format wrong

  • Close any other app using the webcam (OBS, browser, XR Animator)
  • Try a lower resolution in FaceTracker (640×480)
  • Verify webcam works with: ffplay /dev/video0

6. VTube Studio compatibility issue

  • Try switching Proton version in Steam → Properties → Compatibility
  • GE-Proton10-34 works; Proton Experimental may not
  • Launch VTS from terminal to see errors: Right-click in Steam → Manage → Browse local files → then run VTube Studio.exe manually

7. FaceTracker sees no webcams or camera access denied

  • Check: flatpak override --user de.z_ray.Facetracker --device=all
  • The flatpak needs devices=all permission for webcam access
  • Ensure your user is in the video group: sudo usermod -a -G video $USER
  • Log out and back in for the group change to take effect

13.7 FaceTracker Model Reference

Model Index Name Quality Speed Best For
-1 Superfast Lowest Fastest Low-end CPUs, toaster laptops
0 Fastest Low Fast Older hardware
1 Faster Medium Medium Balanced
2 Normal Good Medium Most users (good balance)
3 Default High Medium Recommended — current default
4 Wink optimized High Medium When wink/blink detection matters most

13.8 Full Pipeline Diagram

Webcam (NexiGo N60)
    │
    ▼
FaceTracker (OpenSeeFace via Flatpak)
    │  UDP tracking data (port 11573)
    ▼
VTube Studio (Steam / Proton)
    │  Transparent BG + tracking
    ▼
OBS (Window Capture + Chroma Key)
    │
    ▼
Stream / Recording
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment