Autonomous live browser streaming powered by HeyGen Avatar Realtime, Playwright, LLM scene planning, OBS browser sources, and optional Twitch chat input.
live-streamer runs a 24/7-style show where a HeyGen avatar narrates while a
real browser navigates, scrolls, highlights, and clicks in sync with the spoken
script. It is designed as a working reference project for building live avatar
experiences that need tight timing between speech, captions, browser action, and
stream output.
- Opens and rotates HeyGen Avatar Realtime sessions.
- Serves OBS-ready browser sources for the avatar, captions, activity panels, score overlays, and diagnostics.
- Uses an LLM-powered showrunner to author scenes, narration, browser actions, and cue timing.
- Drives a visible Chromium window with Playwright.
- Schedules visual cues from HeyGen word-level timestamps so browser actions land when the avatar says them.
- Optionally reads Twitch chat, accepts GitHub repo submissions, and queues them into the show.
This is an advanced local demo/reference implementation, not a hosted service. It expects API keys, local processes, and an OBS setup.
flowchart LR
Chat["Twitch chat<br/>(optional)"] --> Queue["SQLite chat queue"]
Queue --> Showrunner["showrunner<br/>LLM scenes + Playwright"]
Showrunner --> Browser["Visible Chromium<br/>repo browsing"]
Showrunner --> Orchestrator["stream_orchestrator<br/>HeyGen session + HTTP/SSE"]
Orchestrator --> HeyGen["HeyGen Avatar Realtime"]
HeyGen --> Orchestrator
Orchestrator --> OBS["OBS browser sources<br/>avatar + captions + overlays"]
- Python 3.11
- uv
- Playwright Chromium
- OBS Studio with obs-websocket enabled
- HeyGen API key with Avatar Realtime access
- Anthropic API key for the showrunner
- Optional: Twitch OAuth token for chat ingestion
- Optional: GitHub token for higher repo-fetch rate limits
# One-time setup
cp .env.example .env
$EDITOR .env
# One-time browser profile setup for the visible Playwright browser
scripts/01-login-browser-profile.sh
# Terminal 1: HeyGen session manager + local OBS/browser-source server
scripts/02-start-avatar.sh
# Terminal 2: LLM showrunner + headed Playwright browser
source .env && scripts/03-run-autonomous-show.sh
# Terminal 3, optional: Twitch chat GitHub URL ingestion
source .env && scripts/05-run-chat-ingester.shOpen local viewer/debug pages:
scripts/04-open-local-views.shStop local processes:
scripts/00-stop-local-processes.shThe login script and autonomous show use the dedicated .browser-profile
directory by default. Do not run both at the same time; Chrome profiles are
single-writer state. Use a dedicated browser account rather than your everyday
Chrome profile.
Add these sources to your OBS scene:
| Source | URL / target | Suggested size |
|---|---|---|
| Browser Source | http://127.0.0.1:8765/ |
1920 x 1080 |
| Browser Source | http://127.0.0.1:8765/captions |
1920 x 220 |
| Window Capture | Playwright Chromium window | Main content area |
Useful local pages:
http://127.0.0.1:8765/debug- timing and playback diagnosticshttp://127.0.0.1:8765/activity- activity screen overlayhttp://127.0.0.1:8765/leaderboard- verdict leaderboard overlayhttp://127.0.0.1:8765/show_stats- show stats overlay
Copy .env.example to .env and fill in the keys you need.
Minimum for the avatar + showrunner:
HEYGEN_API_KEY=
ANTHROPIC_API_KEY=Recommended for longer unattended runs:
GITHUB_TOKEN=
SHOWRUNNER_COST_DAILY_TOKEN_CAP=5000000
OBS_HEARTBEAT_PASSWORD=
OBS_HEARTBEAT_ALERT_WEBHOOK=Required for Twitch chat ingestion:
TWITCH_BOT_TOKEN=oauth:<token>
TWITCH_BOT_NICK=
TWITCH_CHANNEL=
SHOWRUNNER_EPISODE_MODE=true
CHAT_QUEUE_DB=state/chat_queue.sqliteThe showrunner only consumes chat submissions when SHOWRUNNER_EPISODE_MODE is
enabled and CHAT_QUEUE_DB points at the same SQLite file the ingester writes.
| Package | Purpose | Process |
|---|---|---|
stream_orchestrator/ |
HeyGen session lifecycle, HLS/caption/debug pages, OBS browser sources, /producer/* and /activity/* HTTP/SSE APIs. |
Yes |
showrunner/ |
LLM scene planning, episode authoring, Playwright browser control, cue execution, cost caps, notifications, verdict storage. | Yes |
chat_ingester/ |
Twitch IRC reader, GitHub URL extraction, dedupe, ack fallback, SQLite queue writer. | Optional |
script_producer/ |
Compatibility library for marker parsing and word-timestamp cue scheduling. | Library only |
If you prefer explicit commands instead of wrapper scripts:
# Terminal 1
cd stream_orchestrator
uv sync
export HEYGEN_API_KEY=...
STREAM_ORCHESTRATOR_EXTERNAL_PRODUCER_MODE=1 uv run python -m stream_orchestrator# Terminal 2
cd showrunner
uv sync
uv run playwright install chromium
export ANTHROPIC_API_KEY=...
uv run python -m tools.run_autonomous_loop \
--real-llm \
--headed \
--fullscreen \
--max-scenes 3 \
--timeout-sec 600Each package owns its own uv environment and pytest suite.
cd stream_orchestrator && uv run pytest -q # 228 tests
cd ../showrunner && uv run pytest -q # 1377 tests, 7 live tests deselected
cd ../chat_ingester && uv run pytest -q # 114 tests
cd ../script_producer && uv run pytest -q # 55 testsOpt-in live tests:
cd showrunner && uv run pytest -m live -qLive tests require real credentials and may launch real browser or LLM calls.
- This repo is optimized for local streaming and experimentation, not turnkey cloud deployment.
- The showrunner assumes a visible headed browser for the main content capture.
- The optional chat path accepts GitHub URL submissions; general chat-pulse and mention handling are still limited.
script_producer/remains as a small compatibility package becauseword_tracker.pyis shared by the showrunner and has focused test coverage.- Long unattended streams should use the cost cap and notification settings in
.env.example.
- CONTRIBUTING.md - setup, tests, and contribution guidance
- HOST_CHARACTER.md - host voice and editorial style
- chat_ingester/README.md - Twitch chat ingestion
MIT