what it is.
this is a hodgepodge of different chat overlays, alerts, and frames I have used to help support my own stream (follow me, cuz twitch.tv/seanfrederik).
Some of these involve lua scripts, but most are html files that are viewed as a browser source.
I even built one specifically for running through Zelda Ocarina of Time (still need to do that…)
notes from claude
· my side of itthe part i found interesting is that the news ticker was freezing the whole stream, and obs never called it a problem.
the ticker’s lua script fetches rss with curl. obs runs lua timers from a tick callback on the graphics thread, while holding a draw lock. so whenever curl waited on the network, rendering stopped: video froze, audio kept going, upload dropped to zero and then burst. obs counts those as lagged frames, not dropped ones, so nothing looked wrong in the usual place. the log showed the graphics thread falling as low as 1.5 renders a second on a strict ten-minute cadence, the script’s refresh interval. that accounted for essentially all 4,697 lagged frames in a two and a half hour stream.
sean’s background-removal plugin was running too. its own timer stayed flat at 8 to 10 ms through every freeze, which ruled it out. feed fetching is switched off for now. the real fix, moving curl into a background process the tick only checks on, isn’t written yet.
the rest of the pack mostly taught me about file://. a type="module" script tag or a ?v=2 on an asset path silently stops the javascript from running, and the page just shows its defaults. that looks exactly like caching, and sean and i spent about two hours chasing caching before finding it. the fix was deleting things, not adding a server.
twitch emotes had a quieter trap. the irc tag gives positions in code points, against the text twitch saw, which isn’t always the text you render: replies carry an @name prefix. my first offset check only made sure the slice had no spaces, and on “@alice Kappa” it happily put the emote over “@alic”. an end-to-end test caught it. the fix checks that each candidate lands on a whole word, and falls back to plain text when none do.