Status: Complete
Type: Application/Other
Technology: WebSockets, JavaScript, Node.js
Recently one of my side projects is bolstering a YouTube and Twitch channel that I run. Part of this means that I’m streaming, on both. This is a fairly unique use case since most people on Twitch are affiliates who, in essence, sign a contract that states when they’re streaming on Twitch, their live content on Twitch is exclusive. While many upload recordings of their Twitch live streams to YouTube later, this means that a vast majority of users wont be using the chat from multiple platforms making my case fairly niche. Furthermore, most don’t even want to seriously consider streaming to multiple places at once because it’s difficulty in initial setup- which admittedly may be part of why I wanted to do it at all. It’s fun to be special.
In any case, this lead me to wanting to create my chat viewer. And while I had a few difficulties in getting down exactly how I wanted to handle it, I figured out a methodology that I personally like. I’ve split the message gathering, processing, and display into three different stages that are all modular and theoretically interchangeable. This is notably not dissimilar to how layered website architecture works, but since this is a continuous process rather than a data retrieval process it is distinct in the fact that data is constantly being pushed towards the next step rather than being pulled. (Though, my current dirty implementation of things has the display portion constantly pulling data as well)
![](https://trewest.dev/blog/wp-content/uploads/2023/03/image.png)
Input
For input I initially simply wanted to interface with the APIs of these services to quickly grab the chat data as needed. The so called “Correct way” of doing things. This however was quickly ruined by how YouTube’s API for anything data related (Including live chat) having an insufficient default for chat related activities. This is designed to prevent people from grabbing too much data at once and lagging YouTube’s servers, but since the chat API is nonsensically grouped in with it that means that you can only by default keep up with YouTube chat for what a few hours at best, even if it’s only viewing the data. This is, however, the way I’d like to do it if I were providing this as a service to other streamers, but currently I’m developing this a D.I.Y. way of having multiple chats merged into a single window. It is possible to have this query limit changed with an application directly to support, but it’s part of an audit of API usage process that requests detailed information of how the data will be used, and to put it simply, I didn’t want to risk sidetracking the development process to comply.
![](https://trewest.dev/blog/wp-content/uploads/2023/03/image-1.png)
So, instead of creating a service to sell to others (Though, admittedly that’s likely the more profitable approach) I went the route of creating an admittedly somewhat overly complicated process. Instead of running as an application that grabs data directly from APIs and Chat I reworked it into the process that it is now (See the diagram above). And the method I chose for input was simply injecting JavaScript into the website’s own chat viewer. I don’t see this as in any way problematic. It doesn’t do anything to the website since it’s not pulling data from it, the site is sending it on it’s own the way it would to a normal user. We’re just now relaying it to our own service. The major downside of course is that it may have to be reworked in the case that the host sites change details of the chat viewer, but this is a simple process of identifying the element names in the HTML for the sake of collection. In fact, the code I’ve written for the YouTube and Twitch scrapers could’ve been nearly interchangeable had I not been chasing a bug that was entirely my fault. But now I have two ways to show doing essentially the same thing. If I were to spend a little more time on it I’m sure I could make it modular by having some variable names at the top referring to which ones describe the start of a message, which one holds the username, and which is the message’s content.
Collection
The collection step is currently handled by a Node.js based WebSocket server that acts as the go-between for the Input and Output step. In theory, this could be expanded to do things such as chat logging, sentiment analysis, filtering, etc. but currently is a simple relay server. It collects the chat data until a view requests it and then sends it all out and does it again. Perhaps in the future if I am to return to this project I’ll make it more robust (likely out of necessity in order to hide unwanted messages from being displayed, or remove them after being moderated). Something else I’d like to rework it to hold the last hundred chat messages and make the viewers request all the data from since it last requested, so that in the case that the viewer must be restarted it can be done so seamlessly.
Display
Display is the most interesting to talk about, because it’s modular. There’s a good reason why the display portion should be modular and that’s due to the streamer’s preference. I for instance, prefer my chat to hide and fade away given time rather than it staying on screen indefinitely. This is because I also cut and edit stream footage into videos and shorts on YouTube, and find it distracting when a part of the video is obscured by chat that a video viewer may not care for. Others like to have it as a long list showing how conversations have gone during the stream. Then there’s stylistic things like certain creators having a very thematic display of everything preferring a more “chaotic” display of chat where each message has a big space for display and fits in seamlessly with the visual design of their stream. Maybe they’ll want their chatter’s names to display with gradients and the text to be bold, with thick outline. I cannot possibly be sure of everything each creator would want to do and that’s why it’d be important to develop it modularly. Furthermore, it’s easy to find out how to change it, or find someone that can since it runs as a simple webpage. In the future it could even run as a native application that could allow streaming software like OBS to acknowledge a built in transparent background to circumvent issues related to chroma keying.
![](https://trewest.dev/blog/wp-content/uploads/2023/03/image-2-1024x454.png)
The display is also very complicated to handle since different sources also have different extra features for chat. Twitch’s culture for instance has a heavy reliance on different streamer’s custom emoji, for instance that’d have to seamlessly integrate with both display and input but currently doesn’t since I admittedly have not coded it to do so yet. (Input simply sends it to collection as a blank message)
Alas, that’s all I have for this project currently. I don’t know when I’ll be able to ever complete it to my liking, if ever, since I’m entering my final semester of college. But I’ll certainly try to keep sharing what I work on here on my website. By the way, thanks for making it this far!