Speedrun Tools UK: Tech Review of Speed4 TLC, STUK's marathon debut

2nd March 2025

This blog post is a reformatted and slighted edited version of a thread I originally posted to Bluesky during the final day of Speed4 TLC. For likes, comments, and quote posts, see the original thread: https://bsky.app/profile/nickrpgreen.com/post/3ljglclxv222o 


VODs for the marathon can be found on Speed4 TLC's YouTube channel.

As we entered the final evening of @speed4.bsky.social's Speed4 TLC, I wanted to post a thread about the tech and layouts, how I've built it, and an evaluation of how the stream had gone from a tech point of view. Overall, I'm really pleased with where it's at, despite a few bumps initially. 

It's been mentioned on stream but the package I've supplied is part of an effort called Speedrun Tools UK (nickrpgreen.com/STUK). It's my project to provide new or smaller marathons a complete package for running an effective marathon. Automation and having everything in one place is the key driver. This includes:

And my assistance where I'm able to.

The package combines my designs with tech developed by others and available online, which I've repurposed and transformed to fit this package. NodeCG, for example, uses Speedcontrol and various accompanying bundles. The website credits the original works wherever known.

Speed4 TLC's NodeCG Dashboard

As stated, automation is key. I've done marathons where a restreamer has a huge checklist of tasks before a run can go live. Not the case for Speed4 TLC, where if the runner's stream is good, tech pushes a button to start the run, one to start the timer, one to stop the timer, and one to end. Done. The following actions are all automated:

- Scene selection

- Next run in run player (includes all details shown on stream)

- Record start/stop

- Runner stream source selection

- Mics mute/unmute

- Timer reset

- Twitch title

- Back to Intermission after a charity video

How's that gone? It hasn't been without teething problems, this is the package's first event. Friday's big issue was the runner source would change, but because of the source type I was using (a plugin for Streamlink), it would always need refreshing, which couldn't be done via NodeCG. Only on OBS.

The Streamlink sources also proved to be unstable. Whilst I'd obviously tested them, a live environment is very different. We had a few drops, which caused pauses for runs. And trying to use two for the BL2 co-op was impossible. Thanks to everyone for their patience on Friday through those issues.

The whole point of the package is that restreamers should only need NodeCG, reduces having more strangers accessing your PC via Parsec. So before day 2 I swapped out the Streamlink sources for Browser Sources pointing at Twitch popout URLs with some custom CSS to remove the overlay. Much simpler.

OBS showing that whilst at intermission for Stardew Valley, the source controlling the runner's feed automatically updated to the dummy Twitch stream the runner was using.
The details are all managed in Speedcontrol's run editor. The run info and runner/commentator/host details are all pulled from here - no manual editing (except for last-minute changes). The Layout Code on the left tells NodeCG to switch to that layout in OBS when the run starts, whilst the Stream number gets OBS to switch to that runner stream as soon a run ends and switches to intermission.
There is a manual override, which during the marathon needed to be used to update the OBS preview feed - that has since been updated, so as soon as you switch to intermission, the preview now switches to the layout of the next run. There's a manual override for the runner feed as well, in case something's changed.
amyrlinn and Shockwve's Borderlands 2 co-op run. Two Streamlink sources caused major stuttering for both, so I left amyrlinn on one and instead had a Window Capture source point to a VLC window with Shockwve's stream. This caused a large delay between the two which we synced live during the run, which wasn't ideal.

The layouts use speedcontrol-layouts as the core, but I've modified the javascript to add new options, such as adding host and commentator details, as well as the fact the number and size of the host/commentator boxes are dynamic, depending on how many are performing. The images below show it well.

Threach's run of Wizards & Warriors. Threach's comms team included the host and one commentator. You can see they have equal spacing across one line in the 4:3 layout.
helix13's run of Super Monkey Ball Deluxe. Helix had a second commentator, so here the host's box takes up one line, whilst the two commentators share equal space on the line below. Had a third commentator joined, the host's space would have been split to show two on each line.

As for the layout design, that's 90% me. The style of white chalk-like lines on a blue background is based on @biglaw.bsky.social's own stream. I took the design they gave me and adapted what I'd previously designed for FFTK. The positioning of each element stays the same, but the design changes.

amyrlinn and shockwve's Borderlands 2 run. This is the 16:9 two player layout for Speed4 TLC. My design philosophy is that you want to use up the space, but still allow room for the design to show through. Gameplay is always given the maximum amount of space it can - in this case, the two game feeds fill the entire width of the screen.
The original design of FFTK's 16:9 two-player layout. Once the basic design elements were changed, adapting each layout from this to what's used for Speed4 TLC only required a few changes in CSS. 
Speed4 TLC's Intermission screen. I always wanted an intermission screen that showed the game cover for the next run, so I built it. As you'd expect, that's automated - the image file in the background has the same filename as the game title in NodeCG, so when the run updates, the image updates.
The original Intermission screen for FFTK. Because the Intermission screen has less moving parts, a lot more of the Intermission screen is prebuilt in Photoshop. The elements on the left, the background of the music and date overlays, and the backgrounds of Up Next, the game image and host are all created in Photoshop. Only the On Deck areas are coded, so they can disappear as the marathon comes to a close.

All of the layouts you saw in the marathon were adapted from layouts I'd previously built, bar one. Speed4 TLC did get one brand-new one. I didn't want the dancer in a small webcam box for the Pump It Up Phoenix run, so I created this layout to give the camera an equivalent size to the game feed. I do think the finished product looks great.

Zelllooo's run of Pump It Up Phoenix. Uses a custom layout I built specifically for this run so that the runner's webcam has equivalent space to the gameplay.

There's one bit of jank though and that's the donation total. As hard as I've tried, I cannot get Tiltify integration with NodeCG to work. So the donation total is actually a browser source, pointing at https://tiltify.com/+speed4/speed4-tlc, cropped to the donation total with some custom CSS applied.

The browser source properties for the donation total. The entire page is hidden, expect for the class that manages the donation total text (which also manages the donation target and current incentive text). Some further CSS makes that text white and larger, and the extra elements have been cropped out.
debeaunairVT's run of Kitsune Tails. debeaunair and their commentators used a pngtube-style program called Discord Reactive Images which has their avatars react based on their Discord call. The fact that all their details were visible directly below made for a really cool setup.

I'm really proud of the layouts. Feedback from my time at Pixel Perfect was always that there was too much dead space, and the game feed wasn't big enough. With these layouts, I feel like every element is optimised well, and the way I've built the CSS means they're so easy to adapt.

The runner OBS with my Xbox Series S being captured.

The runner OBS proved challenging and had a couple of updates after it was initially shared. I want to thank the runners for their patience and for dealing with those changes, especially @xoxogossipgreg.bsky.social and @shoujo.tv as they got a new one only the day before their run with a tweak for their race.

The runner OBS is designed so that all the runners need to do is point the appropriate sources at their game, mic, Discord and webcam and then do a bit of audio balancing. Everything else is done for them, including the positioning of those sources in each scene and splitting their audio channels.

All comms audio for the run comes from the player's stream - it's the easiest way of having everyone in sync with the gameplay. That was the cause of the first runner update - before this event all comms audio was to come from Discord, but I changed the plan and forgot to update the runner OBS.

A stereo pan filter on the runner's microphone. A common technique a lot of marathons use is to have commentary sent down one stero audio channel and gameplay sent down the other. The stream OBS picks up the stereo audio, separates the two channels into different sources and then rebalances so both go to the stream down both channels again. You lose any directional stereo sound from the gameplay, but you'd very likely not notice it anyway.
The Live Audio Monitor on NodeCG. On our end, the sources are split out, so we can at least make adjustments to the gameplay and commentary on the fly. Individual commentators need balancing in Discord, but as long as the setup volunteer does this well, it causes no issues. Additionally, we duplicate each source to have one that goes to the stream, and one that is only monitored by OBS. This allows audio balancing to be performed during intermission.

The runner OBS uses Twitch Enhanced Broadcasting to automatically select optimal settings for the runner based on their hardware. Runners don't have to manually adjust the bitrate or select profiles. This did cause an issue as TEB also allows you to send multiple feeds at different resolutions.

When we switched to capturing runner streams directly from Twitch, an issue occurred where if a runner was sending multiple feeds, the browser source would automatically grab the worst resolution and there was no way to change it. If you saw the start of Balatro or Peglin, that's why it looked bad.

Twitch Enhanced Broadcast allows you to send multitrack video, so viewers can watch your stream in multiple resolutions.
bystandertim_'s Peglin run. The runner OBS was streaming with multiple video feeds and for some reason, the stream OBS browser source would only return the 240p stream. So when the run went live, it looked like this.

The solution was simple, but another change for the runners. Keep TEB enabled to control their settings, but have them turn off the multitrack auto function and limit it to 1 track only. That way, it'll only send the best option, and the stream OBS browser source only has one feed to choose from.

The final change, which only affected the two racers, was to add universal clock so we could easily sync the runners feeds. There currently isn't any functionality to add a delay via NodeCG, so an admin would've needed to access my PC via Parsec to add it, had I not still been awake at 2am my time to do it myself.

As was pointed out by @schalakitty.bsky.social on Discord, we could tell if the runners had caught the instruction to make the TEB change by checking the setting on the dummy Twitch stream. If only one resolution was available, they'd made the change. As the dummy accounts will never be affiliate, they'll never get access to more feeds than is sent by the runner. 
A new scene on the stream OBS showing the internet time of both racers. This is a very common practice for marathons and I'm hoping I can make it accessible via NodeCG in the future.

A rocky road with lots of bumps along the way. I thank everyone who's ridden over those bumps for handling it so well. Following some of the feedback during the event and from a form I used to the runners and tech, I've got a little bit of work to do with making the audio sound better. The errors will be worth it if I learn from them and make changes to improve for the next event. On the fly during the last day, I made the stream preview bigger to help spot the 240p issue!

The old size of the stream preview.
The new, much larger size of the stream preview.

That's probably all that's noteworthy to talk about. I've got plans for changes elsewhere with the schedule workbook and the guides all need a bit more tweaking with some of the changes implemented over the weekend. You can find out more about those here on the website.

The next major step is to make this whole thing portable. Right now, the stream and NodeCG are being run from my PC, which is fine, but if others want to use this package and I'm not available, they can't. I need to make some default layouts and tidy other bits up, but then I'll work on a release.

In the meantime, if you've got an event that needs a place to start with their tech, or you want to look at how you can improve your existing tech, check me out. My DMs on Bluesky are always open or you can email me at info@nickrpgreen.com.

It's mind-blowing that the very first event my package has been used for raised over $7,000 for Transgender Law Center. Whilst I obviously just explained the credit I take for that, the organisation of this event, particularly at this pace, has been fantastic.

@biglaw.bsky.social and the rest of the @speed4.bsky.social admin team should be extremely proud of what they've accomplished. It is very rare to see a brand new marathon pop off as hard as this one has and it has been a genuine pleasure to be part of that experience. Congrats to everyone involved.

I enjoyed finally being able to stick to one lane. Those who worked with me at Pixel Perfect will know I had to be EVERYWHERE. I organised almost all aspects of those events, except for tech (though I was still involved with it). Being able to focus solely on tech for this has been refreshing.

Because I'm UK based and the marathon was US based, I was asleep during each day's close. I slept in my studio (which is also a spare bedroom), with my speakers on loud so if there was a major tech issue whilst I was asleep, I could be woken (BigLaw had to play a YouTube video of the Discord ringtone on the second night because a call failed!).

The final intermission screen of Speed4 TLC. The donation total was $7,274