Viewers type in a YouTube live chat. Each message is moderated, rewritten into a house style, generated as a 5-second clip by MiniMax H3-Max, moderated again as video, and put on air about 40 seconds later. Between new clips the channel replays its library.
The requester is recorded in the log and in the clip's library entry. It is not drawn on the video, so a viewer cannot tell which clip is theirs. That is the largest missing feature and it is the first item in TODO.md.
A one-day experiment. It ran live on YouTube on 2026-08-30, served 19 viewer prompts from 8 people, and cost $31.05. It is not a product, it is not maintained, and the author is not running it any more. The code is here because it works and someone else may want it.
It ran here:
- https://www.youtube.com/watch?v=57kEzycZBvY
- https://www.youtube.com/watch?v=dvyXxIuk88Q (the first broadcast, ended by the RTMP incident described under Broadcasting to YouTube)
Pointing this at a YouTube channel puts that channel at risk. Strangers write the prompts. Four automated filters screen them on the viewer-prompt path, and each one drops the clip rather than airing it when a service is unavailable or a key is missing. They will still miss things.
They score policy categories such as hate, sexual content and violence. They do not score taste, cultural context, trademark, impersonation, or whether YouTube will issue a strike. A real example from the one day this ran: a viewer asked for people in thobes and kaffiyehs, and the resulting clip showed recognisable Gulf Arab dress on humanoid figures dancing in a club. It passed the chat filter, the rewritten-prompt filter and the image filter, because it is not hate speech and not violent. A human noticed it and pulled it. The prompt rewriter now forbids real-world religious, ethnic and national markers, and nothing reviews output for taste.
If you run this on a channel you care about, review clips before they air. The code does not do that for you.
You also pay the API bills, and you are responsible for what the channel broadcasts.
YouTube live chat
-> OpenAI moderation on the raw message (refuses on failure)
-> gpt-4.1-mini rewrites it into house style (refuses on failure)
-> OpenAI moderation on the rewritten prompt (refuses on failure)
-> MiniMax H3-Max generates a 5-second clip
-> OpenAI image moderation on 3 sampled frames (refuses on failure)
-> jumps the queue, airs next, credited to the viewer
-> joins the library and replays afterwards
About 40 seconds from message to broadcast when the queue is empty, 50 to 70 including YouTube's own latency.
Three ideas are worth knowing before reading the code.
The publisher is a separate process. It owns the RTMP connection and holds the FIFO
open O_RDWR, so the controller can crash, be restarted, or be edited without the
broadcast noticing. This matters more than it sounds: on the day this ran, a ten-second
RTMP gap with YouTube's Auto-Stop enabled ended the broadcast, changed the video ID, and
killed every link that had already been shared.
Generation is windowed. One clip per window regardless of how many people are waiting. A first-in-first-out queue would make cost scale with audience size, so a busy chat would drain the balance in minutes. Below a threshold everyone is served in turn; above it the window draws at random, because a long queue promises a slot that arrives after the viewer has left.
The library rotates. Generation runs at roughly 0.4x realtime per worker and costs $0.05 per second of video, so a continuously unique 24/7 channel is not affordable. Clips are keyed by MiniMax task id, never overwritten, and replayed between new ones.
You need two accounts. Neither has a free tier that covers video generation.
MiniMax does the video. Get a key at
https://platform.minimax.io/user-center/basic-information/interface-key. The key type
matters and cost an hour to work out: MiniMax issues a Subscription Key (sk-cp-) for
its Token Plan and Credits products, and a separate pay-as-you-go API key (sk-api-).
The H3 video series is not available on Token Plan or Credits. Sending a sk-cp- key
returns TokenPlan or Credit does not currently support MiniMax-H3 series models. Create
the pay-as-you-go key and top up the account balance, which is a different wallet from
credits. The minimum single top-up is $25.
OpenAI does moderation and prompt rewriting. Get a key at
https://platform.openai.com/api-keys. The moderation endpoint
(omni-moderation-latest) is free, including image moderation. Rewriting uses
gpt-4.1-mini at roughly $0.0002 per prompt, so it rounds to nothing.
| MiniMax, 123 clips | $31.05 (most at 480P, a few at 768P and 2K while testing) |
| OpenAI moderation, several hundred calls | $0.00, the endpoint is free |
| OpenAI rewriting, about 25 prompts | under $0.01 |
| Two MiniMax top-ups, tax included | $53.20 charged, $49.45 usable |
| Left over | about $18 |
MiniMax publishes no 480P price. This one was measured by watching the balance move.
| 480P | $0.05 per second of video |
| 768P | $0.08 per second (published) |
| 2K | $0.13 per second (published) |
| One 5-second 480P clip | $0.25 |
| One clip per minute | about $15/hour |
Generating 24 hours of unique content would cost about $4,300 a day, which is why the library rotates instead.
MAX_BILLABLE_SECONDS is the real ceiling. Seconds already spent are recomputed from the
clip ledger at startup, so restarting does not hand the process a fresh budget.
STOP_AT_USD stops generation while a reserve remains, but it only works if you also set
BALANCE_START_USD to your own account balance. There is no default, because guessing
someone else's balance would produce a guard that never fires. Left blank, the floor is
disabled and the process says so on startup. Neither value queries MiniMax; both are
computed from the local ledger, so top up again and you must update BALANCE_START_USD.
MAX_CLIPS only catches runaway loops and should sit well above what the money ceiling
allows. A tight value silently halts generation with budget still available.
PRICE_PER_SECOND affects the printed tally only and does not control what you are
charged.
Node 22+, ffmpeg with libx264, and a Mac or Linux box that can encode video in real time.
The library and ledger start empty. On a fresh clone there is nothing to broadcast, so the
stream shows a generated SMPTE test card until the first clip exists. The balance floor
does nothing until at least one clip has been generated, because it is computed from the
ledger. A MiniMax
pay-as-you-go API key (the sk-api- kind; Token Plan and Credits keys are rejected for the
H3 series), an OpenAI API key, and a YouTube stream key if you want to broadcast.
The defaults publish nothing and spend nothing.
cp .env.example .env # fill in MINIMAX_API_KEY and OPENAI_API_KEY
npm run preflight # tells you whether the key works and whether it has balance
npm start # local preview at localhost:8080, library only, no generation| command | what it does |
|---|---|
npm start |
local HLS preview, no generation, no spend |
npm start -- --generate |
generates from prompts-interdim.json |
npm start -- --generate --youtube |
sends video to your RTMP destination. If YouTube Auto-Start is on, this puts you publicly live |
npm start -- --chat --video=<id> |
reads live chat and generates from viewer messages. This spends money |
Create the stream as a scheduled stream through the Manage tab, not the instant "Stream
now" key. A scheduled stream tolerates brief data loss and keeps its video ID; the instant
one ends the broadcast on any disconnect, and the URL you shared stops working. Share
youtube.com/@yourhandle/live, which always resolves to whatever is currently live.
scripts/broadcast.sh is the unattended entrypoint. It starts the publisher once, keeps
the controller alive around it, and holds the machine awake with caffeinate:
LOTTERY_WINDOW_SEC=60 MAX_BILLABLE_SECONDS=100 \
./scripts/broadcast.sh --youtube --only=interdim --chat --video=<video id>--generate is honoured only on the first launch. Restarts drop it and rebroadcast the
library, because each new process resets its own attempt counter and a crash loop would
otherwise re-spend on every restart.
Note that --youtube on its own already publishes. It does not need --generate; the two
switches are independent, and --chat spends money whether or not --generate is set.
The chat reader polls YouTube's internal innertube endpoint, the same route the chat iframe
uses. It needs no authentication, which is why the one-day build used it. It is
undocumented, can change shape without warning, may fall foul of YouTube's terms, and the
consequences land on your account. The supported alternative is the YouTube Data API with
OAuth (liveChatMessages), which also lets a bot reply.
- Nothing reviews generated video for taste or cultural appropriateness.
- One lottery entry per channel id. Several accounts get several entries. YouTube's own slow mode or subscribers-only chat is the practical mitigation.
- A FIFO write can block indefinitely if the publisher's ffmpeg dies in a particular way, because the controller cannot see that the reader is gone.
- No singleton lock on the controller. Two ran at once during development, which risks double spending.
- Output is 480p at 1.5 Mbps and looks soft. MiniMax returns 5.6 Mbps; the publisher discards most of it, and YouTube gives 480p inputs a low bitrate allocation.
- On a laptop, closing the lid ends the broadcast.
@levelsio launched a similar chat-driven AI channel, Infinite Slop, one day earlier. It is closed source. This is an independent build.
MIT, covering the code in this repository. It does not cover generated clips, model outputs, or third-party services.
Provided as is, with no warranty. Not affiliated with YouTube, MiniMax or OpenAI. You pay for API usage, you are responsible for what your channel broadcasts, and generated video can violate platform policy after passing every filter here. The author is not running this and cannot support your stream.