Twitch and YouTube live chat in one overlay for your stream.
To read your YouTube live chat, chat-aggregator logs in to your YouTube account. Because of how YouTube’s API is billed, you need your own (free) Google Cloud project for that. This takes about 10 minutes, once.
YouTube counts API usage (“quota”) per Google Cloud project, not per user. A project gets 10,000 units per day for free. Reading live chat costs about 1,500–1,800 units per hour of streaming: YouTube currently cuts the chat connection every ~10 seconds (a known bug on Google’s side, with an open ticket), and every reconnect costs 5 units. So one project covers roughly 5–6 hours of streaming per day, and a shared project for all users couldn’t even cover one channel. With your own project, your quota is yours alone.
Checking whether you’re live while you’re offline is cheap (1 unit every 2 minutes, every 30 seconds shortly before a scheduled stream), so leaving the app running all day is fine. When you go live without scheduling the stream, chat appears within those 2 minutes, including the messages from the first minutes.
chat-aggregator → Create. Select the new project.No billing account or payment method is needed.
APIs & Services → Library → search YouTube Data API v3 → Enable.
This is the page Google shows when you log in. Google’s menus move around from time to time; the section is called Google Auth Platform (older name: OAuth consent screen).
chat-aggregator, and your email as the
support address. Audience: choose External. Add your contact
email, agree to Google’s policy and Create.Branding: to be allowed to publish (next step), Google needs a homepage, a privacy policy and their domain. Use chat-aggregator’s:
| field | value |
|---|---|
| Application home page | https://isneeze.github.io/chat-aggregator/ |
| Application privacy policy link | https://isneeze.github.io/chat-aggregator/privacy/ |
| Application terms of service link | leave empty |
| Authorized domains | isneeze.github.io |
Don’t upload a logo: with a logo, Google requires a full app verification. Click Save at the bottom.
Audience: click Publish app and confirm, so the status becomes In production.
Why: while an app is in Testing, Google makes logins expire after 7 days, and you’d have to log in again every week. Publishing does not require Google’s verification for an app only you use: Google just shows a warning when you log in (step 5), and allows up to 100 accounts.
Afterwards Google shows a yellow banner: “Your app requires verification … please submit your app for review.” That’s because reading YouTube counts as a sensitive permission. Ignore it; don’t submit. Verification is meant for apps used by many strangers (it asks for a demo video and domain ownership).
Just trying it out? You can skip branding and publishing: stay in Testing and add the Google account that owns your YouTube channel under Audience → Test users (without that, Google refuses the login). You’ll have to log in again every 7 days.
You don’t need to add anything under Data Access (scopes): chat-aggregator asks for its one permission, read-only access to your YouTube account, when you log in.
chat-aggregator desktop.It must be the Desktop app type: other types don’t accept the local login
address the app uses (http://127.0.0.1:<port>).
The client secret of a desktop app isn’t a real secret in Google’s eyes (any installed program could be taken apart to find it), but don’t post it publicly either.
config.toml in chat-aggregator’s settings
folder, readable only by your user account.)The login is stored in your system’s keyring (Keychain on macOS, Credential Manager on Windows, Secret Service such as gnome-keyring or KWallet on Linux; without one, a file only you can read in the settings folder). You only do this once. Log out in the YouTube section (e.g. to switch channels) removes it.
Under Add a source, choose YouTube (your broadcasts) → Add.
chat-aggregator finds your current or next broadcast by itself (including unlisted and members-only streams), waits cheaply until it starts, and attaches to its chat. After the stream it goes back to waiting for the next one. The source’s light: 🟢 working (or waiting for your broadcast), 🟡 recovering by itself, 🔴 no chat until something changes (e.g. log in again, or the daily quota runs out; the text next to it says which), ⚪ switched off.
To follow someone else’s stream instead: YouTube (a video) with the
video’s id (the part after watch?v= in its URL). It uses your login too.
Only needed to read a video’s chat without logging in. Same project: APIs & Services → Credentials → Create credentials → API key. Then edit the key: under API restrictions choose Restrict key and tick only YouTube Data API v3, so the key is useless for anything else. In the app, paste it into ⚙ Settings → Connection → YouTube API key. It uses the same project’s quota.
The same settings work from the terminal. Create a commented config file once:
cargo run -p chat-engine --example run -- --init-config
It goes into chat-aggregator’s settings folder
(~/.config/chat-aggregator/ on Linux, ~/Library/Application
Support/chat-aggregator/ on macOS, %APPDATA%\chat-aggregator\ on
Windows). Fill in the [youtube] section and add your broadcasts:
[youtube]
client_id = "1234567890-abc….apps.googleusercontent.com"
client_secret = "GOCSPX-…"
[[sources]]
type = "youtube"
(The environment variables YOUTUBE_CLIENT_ID and YOUTUBE_CLIENT_SECRET
override the file.) Then log in once, and start:
cargo run -p chat-engine --example run -- --youtube-login # as in step 5
cargo run -p chat-engine --example run # everything in config.toml
cargo run -p chat-engine --example run -- --youtube-logout # to log out
The terminal shows the same status lights per source.
| message | cause and fix |
|---|---|
Google shows redirect_uri_mismatch or invalid_request |
the client isn’t of type Desktop app (step 4) |
invalid_client |
client ID or secret mistyped, or from another project: Change client in the YouTube section |
access_denied / “app is being tested” |
the app is still in Testing and your account isn’t a test user (step 3) |
YouTube login required: Google rejected the stored login |
the login expired or was revoked. If it happens weekly, the app is still in Testing (step 3). Connect YouTube again. |
this Google account has no YouTube channel |
you logged in with a different Google account than the channel’s: Log out, connect again with the right one |
YouTube quota used up for today; resuming at … |
the daily quota is used up; the source continues by itself after midnight Pacific time |
YOUTUBE_CLIENT_ID must be set (headless) |
the [youtube] section of config.toml is missing |