Skip to content

89891383/StreamChango-Chatango.com-Chat-Overlay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StreamChango

Modern, transparent Chatango chat overlay for OBS, vMix, Streamlabs and any streaming software that supports Browser Sources.

A self-hosted alternative to jChat / StreamElements chat boxes — but for Chatango rooms instead of Twitch / Kick / YouTube. Bot connects anonymously, no account required. Real-time over WebSocket. Fully customisable. Multi-room. Looks great on top of any scene.

yourdomain.tld/overlay        ← config panel (manage rooms, build OBS URL)
yourdomain.tld/overlay/view   ← the transparent overlay (paste this into OBS)

Features

Looks like a real Twitch chat overlay

  • 100% transparent background — no Custom CSS in OBS, just paste & go
  • Bubble or plain mode — with or without a translucent background per message
  • Adjustable background opacity (0–100%)
  • Avatars in a clean circle, configurable size, anons get no avatar
  • Smooth message-in animation with fade-out after N seconds (configurable)

Inspired by jChat / BotRix

  • 3 size presets: Small / Medium / Large — sets sensible font + avatar
  • 12 fonts to choose from: Inter, Roboto, Lato, Noto Sans, Open Sans, Montserrat, Bebas Neue, Press Start 2P, Comfortaa, Source Code Pro, Wallpoet, Indie Flower (all from Google Fonts, preloaded)
  • Text stroke (outline) in 5 levels — great for bright scenes
  • Drop shadow in 4 levels — for extra contrast on busy backgrounds
  • Small caps and ALL CAPS modifiers
  • Custom font and avatar size sliders — override the preset

Inline images

  • URLs ending in .jpg, .jpeg, .png, .gif, .webp, .bmp or .avif are rendered as <img> tags directly in the message
  • Configurable max image height (default 180 px)
  • Toggleable per-overlay (?images=0 to disable)

Filters

  • Hide one or more bot accounts by name (?hidebot=raszeibot,fbicat)
  • Hide all messages starting with ! (commands)
  • Hide all anonymous users
  • Hide every avatar globally

Honour Chatango user styles

  • Username colour from chatango is respected (with bug workaround for the upstream chatango-lib zfill bug — "FFF" used to render as #000FFF)
  • Message text colour from chatango is respected
  • Both can be turned off individually if you'd rather have a uniform look

Operations

  • Multi-room — one bot process serves any number of rooms; rooms can be added & removed live without restarting the bot
  • Auto-reconnect WebSocket with exponential backoff (1 s → 15 s)
  • Per-room ring buffer of the last 40 messages so a fresh viewer immediately sees activity
  • Persistent room list in data/rooms.json survives restarts
  • systemd unit included, hardened with NoNewPrivileges / PrivateTmp
  • OBS-friendly: no Custom CSS needed, transparent by default

Architecture

                                          ┌──────────────────┐
   chatango.com  ───websocket───────────► │  OverlayBot       │
   (s{N}.chatango.com:8081)               │  (chatango.Client)│
                                          │  joins all rooms  │
                                          └────────┬──────────┘
                                                   │ on_message
                                                   ▼
                                          ┌──────────────────┐
                                          │ ChatangoManager  │
                                          │  ‒ history buffer│
                                          │  ‒ WS client pool│
                                          └────────┬─────────┘
                                                   │ broadcast()
                       ┌───────────────────────────┼───────────────────┐
                       ▼                           ▼                   ▼
             ┌────────────────┐         ┌────────────────┐    ┌────────────────┐
             │ OBS overlay #1 │         │ OBS overlay #2 │    │  another viewer│
             │ (websocket)    │         │ (websocket)    │    │ (websocket)    │
             └────────────────┘         └────────────────┘    └────────────────┘

Single Python process. One bot is a singleton — this is why the service runs with --workers 1.

Stack: Python 3.10+, FastAPI, uvicorn, neokuze/chatango-lib. Frontend: vanilla JS + CSS, zero frameworks, zero build step.


Quick start

Requirements

  • Linux server (tested on Debian / Ubuntu)
  • Python 3.10+
  • nginx (for SSL termination & reverse proxy)
  • A domain pointing at the server

Install

# 1. Get the code
git clone https://github.com/YOUR_USERNAME/streamchango.git /opt/streamchango
cd /opt/streamchango
chmod +x run.sh

# 2. Python virtualenv
apt install -y python3-venv python3-pip git
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -r requirements.txt
deactivate

# 3. Quick test (Ctrl+C when done)
./run.sh &
sleep 4
curl http://127.0.0.1:8765/overlay/api/health
# {"ok":true,"active_rooms":["chatraszei"]}
kill %1; wait

# 4. systemd
cp streamchango.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now streamchango
systemctl status streamchango
journalctl -u streamchango -f      # live logs

Configure nginx

Open your domain's nginx server block (e.g. /etc/nginx/sites-available/yourdomain) and add the two ^~ /overlay location blocks from nginx-streamchango.conf inside it.

The order matters: /overlay/ws/ MUST come before /overlay, and ^~ guarantees they take precedence over any / block you may have for another app.

nginx -t && systemctl reload nginx

Add to OBS

  1. In your scene: + → Browser
  2. URL: copy from the Copy button on https://yourdomain.tld/overlay
  3. Width: 420, Height: 720 (or whatever fits your scene)
  4. Custom CSS: leave empty — the page is already transparent
  5. Tick Refresh browser when scene becomes active

URL parameters (full reference)

Build these in the panel UI, or hand-edit if you know what you want:

Parameter Values Default Description
room <n> (required) Chatango room name
size small, medium, large medium Preset for font + avatar size
font 011 0 0=Inter, 1=Roboto, 2=Lato, 3=Noto Sans, 4=Open Sans, 5=Montserrat, 6=Bebas Neue, 7=Press Start 2P, 8=Comfortaa, 9=Source Code Pro, 10=Wallpoet, 11=Indie Flower
fontsize 048 0 (use preset) Override font size in px
avatarsize 080 0 (use preset) Override avatar size in px
bg bubble, plain bubble Show translucent message background
bgalpha 0100 55 Bubble background opacity (%)
stroke 04 0 Text outline: off / thin / medium / thick / thicker
shadow 03 1 Text shadow: off / small / medium / large
animate 0, 1 1 Smooth animation when new messages arrive
fade 0300 30 Auto-hide messages after N seconds (0 = never)
max 5100 30 Max visible messages on screen
hidebot csv (none) Comma-separated bot usernames to hide
hidecmd 0, 1 0 Hide messages starting with !
hideanon 0, 1 0 Hide all anonymous users
hideavatar 0, 1 0 Hide all avatars
images 0, 1 1 Render image URLs as inline images
imagesize 80400 180 Max image height in px
smallcaps 0, 1 0 Render text in small caps
allcaps 0, 1 0 Render text in ALL CAPS
namecolor 0, 1 1 Respect username colour from chatango
msgcolor 0, 1 1 Respect message text colour from chatango
debug 0, 1 0 Show connection status pill (top-right)

Example URL with everything customised:

https://yourdomain.tld/overlay/view
  ?room=chatraszei
  &size=large
  &font=5
  &bg=bubble
  &bgalpha=60
  &stroke=2
  &shadow=2
  &fade=30
  &max=25
  &hidebot=raszeibot
  &hidecmd=1
  &images=1
  &imagesize=200

REST API

Method Endpoint Description
GET /overlay/api/health Health check + currently joined rooms
GET /overlay/api/rooms List rooms (persisted + active)
POST /overlay/api/rooms Add a room. Body: {"room":"<n>"}
DELETE /overlay/api/rooms/{room} Remove a room
WS /overlay/ws/{room} Live message stream as JSON

WebSocket payload format:

{
  "type": "message",
  "id": "abcd1234",
  "room": "chatraszei",
  "time": 1745020800.123,
  "body": "Hello world https://i.imgur.com/abc.png",
  "user": {
    "name": "raszei",
    "showname": "Raszei",
    "isanon": false,
    "avatar": "https://fp.chatango.com/profileimg/r/a/raszei/thumb.jpg",
    "name_color": "#FF5500",
    "font_color": "#FFFFFF"
  }
}

name_color and font_color are null when the user never picked a colour (or picked black, which is treated the same since black is unreadable on stream overlays).


Bug fixes / workarounds applied to chatango-lib

chatango-lib is great but has a few rough edges that StreamChango works around transparently:

  1. Colour zfill bugutils.py:428 does str(self._name_color).zfill(6) which turns the 3-char shorthand "FFF" into "000FFF" (almost black, not white). We bypass the broken property and read the raw _name_color / _font_color directly, then expand 3 → 6.
  2. Client.stop() race — iterates over self.rooms while disconnect() mutates it → RuntimeError: dictionary changed size during iteration. We replicate the disconnect loop with a snapshot.
  3. Internal display markers — chatango-lib prefixes anonymous user names with ! and temporary nicks with #. The official chatango UI never shows these. We strip them before rendering.

Troubleshooting

The bot doesn't join a room. Check the logs: journalctl -u streamchango -f. The most common cause is an invalid room name — the regex is ^[a-z0-9][a-z0-9_-]{0,19}$.

Overlay shows "Connecting..." and never connects. Check your nginx error log. The most likely cause is missing Upgrade $http_upgrade headers in the WS location block, or Cloudflare in front of the domain stripping WebSockets (enable "WebSockets" in your CF zone settings under Network).

A user has no avatar. Anons never have one (by design). Logged-in users who never set a profile picture also won't have one — chatango simply doesn't host an image for them.

Image URL renders as a link instead of an image. The URL must end in a recognised extension. https://i.imgur.com/abc → link. https://i.imgur.com/abc.png → image. Sites that hot-link without an extension (like some .gifv URLs from imgur) will not be recognised.

Two viewers means two bots? No. There's one OverlayBot per process and each viewer is just a WebSocket subscriber. This is also why --workers 1 is mandatory in run.sh: a multi-worker setup would mean multiple bots connecting to the same chatango room.

Messages are duplicated. StreamChango deduplicates by id. If you still see doubles, please open an issue — chatango-lib may have changed its protocol.


Contributing

PRs welcome. Some easy first wins:

  • Add more fonts (just add them to the Google Fonts URL in static/overlay.html and to the FONTS array in both static/js/overlay.js and static/config.html)
  • Per-room overlay presets stored server-side (so streamers don't need to re-paste a URL when they change settings)
  • Translation of the panel UI (currently Polish + English mix)
  • Native mobile-friendly panel layout

License

MIT — do whatever you want with it.

chatango-lib (a transitive runtime dependency) is GPL-3.0; we use it unmodified through pip, so this project remains MIT-licensable.


Credits

  • neokuze/chatango-lib — async Python client for Chatango that does all the heavy WebSocket work
  • giambaJ/jChat — inspiration for the customisation options (size / font / stroke / shadow / animate / fade)
  • BotRix — reference for the streamer UX

About

Modern transparent chat overlay for Chatango rooms - customization for OBS streamers

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors