Tinkering with Twitch Chat sentiment

Just a simple one-afternoon concept build.

This little idea has been in my head for almost 8 years. Actually wrote a little piece on it a long time ago that I cannot seem to find describing the difficulty of interpreting, even for humans, emotion in Twitch Chat. But… How cool would it be to use sentiment analysis of Twitch Chat to trigger things on stream or to use that data to improve a broadcast? The problem always, and still, is that doing a proper sentiment analysis at the moment is almost impossible. I have never seen a model or program that can accurately predict the sentiment of chat. Mainly because you would need to have the context, the culture, and also the video content nailed down so precisely while still being able to act on random unpredictable events. Not something I would be able to solve in my spare time at my little attic office. At the bottom of this post you can find an example of what I did with crowd noises and the calculated sentiment.

So let’s do a quick one-afternoon build of already existing packages in NodeJS to see if I can come close using simple sentiment analysis in real-time of Twitch Chat. This is by no means scientifically sound and just a little fun project to obtain a basic average sentiment score to use for other fun applications. I am going to assume some basic understanding of NodeJS for this if you want to build it yourself. In this post I will only show you how I got the sentiment score and not how I did the crowd audio as that part of the afternoon build was way to hacky for my taste.

I am aware of the Amazon Workshop page that also explains how you can do it with their Comprehend and other tools to make a full fletch application but didn’t feel like setting that up with the services etc.

Starting a NodeJS project

I use Visual studio code and the terminal that comes with it. To start a NodeJS project make sure Node is installed on your computer and just type npm init in the terminal to start setting up the project. For this purpose, I left all the fields blank as I don’t plan to distribute the project as something official. In the main folder make a file called index.js what is our main program (just call it anything you want, but I am just used to doing index.js as a starting file).

Getting the Twitch Chat

To start off we need the actual Twitch Chat imported. Luckily Twitch still gives access to the IRC channel without going through too many authentication hoops and verification steps. Often I use the dank-twitch-irc package, but for this build, I went with the tmi.js package as the dank sometimes gives websocket conflicts with other packages that I just don’t feel like resolving for this purpose. The packages basically do the same. To install the package type npm install tmi.js . The basic code is straight forward and the only thing you will need is to get the OAuth from the Twitch Chat Password Generator.

const tmi = require('tmi.js');
const client = new tmi.Client({
	options: { debug: true },
	identity: {
		username: 'bot_name',
		password: 'oauth:my_bot_token'
	},
	channels: [ 'my_channel' ]
});
client.connect().catch(console.error);
client.on('message', (channel, tags, message, self) => {
	if(self) return;
	}
});

Make sure to fill in the identity with that retrieved OAuth password and bot_name can be whatever you want (except for anything offensive). You can watch multiple channels, but for this purpose, we only need to watch one channel by replacing just what channel you want to retrieve the messages from. Paste the following code in the index.js file with the correct date. When you have everything set up and start the script in the Visual Studio terminal with node index.js you will get the following output when watching summit1g as a channel. Just simply print the channel, username, and the chat message that they send in real-time. Funnily enough at the moment what I see in the terminal is slightly faster, talking ms here, than watching the chat on the channel.

Doing a simple sentiment analysis

Told you this is was going to be just a simple sentiment analysis. Using the package sentiment I am going to weigh every message and give it a sentiment score. This package uses the AFINN-165 and Emoji Sentiment Ranking to analyze text with emojis to give it a sentiment score. The score is based on the lists of AFINN-165 and the Emoji Sentiment Ranking that have accumulated word with their rankings after researching the most likely they are to have a positive or a negative feeling attached to it. If it cannot find any of the words it will output as a 0 meaning neutral. To install it just simply type npm install sentiment in the terminal. Let’s add the necessary code so we can see the sentiment of every message by doing the following:

var Sentiment = require('sentiment');
var sentiment = new Sentiment();

const tmi = require('tmi.js');
const client = new tmi.Client({
	options: { debug: true },
	identity: {
		username: 'bot_name',
		password: 'oauth:my_bot_token'
	},
	channels: [ 'my_channel' ]
});
client.connect().catch(console.error);
client.on('message', (channel, tags, message, self) => {
	if(self) return;
	console.log(sentiment.analyze(message).score)
});

When you run the code you will get something like this. The only thing that is happening at the moment is that every message will get a score with the perceived sentiment and print it out after printing the message first. You could probably already use this for something if you would like, but with a high volume of Twitch chat messages, you probably want to make an average over a certain period for it to have some meaning.

Calculating the moving average

Thought a little bit longer about this part as you don’t want to just want an average as that will get you only the average over the entire time that the script is running so needed a way to calculate the moving average. Basically making sure that newer messages are more important than older messages for the average sentiment score. Started to calculate it myself, but of course, there is just a package for that as well. moving-average is just a simple package that can be used to do different calculations of the data coming in. Implementing that after running npm install moving-average will give the following script where we do the interval in 1 minute and print out the score calculated.

var Sentiment = require('sentiment');
var sentiment = new Sentiment();
var timeInterval = 1 * 60 * 1000; // 1 minute
var MA = require('moving-average');
var ma = MA(timeInterval);
var sentimentAverageScore = 0;



const tmi = require('tmi.js');
const client = new tmi.Client({
	options: { debug: true },
	identity: {
		username: 'bot_name',
		password: 'oauth:my_bot_token'
	},
	channels: [ 'my_channel' ]
});


client.connect().catch(console.error);
client.on('message', (channel, tags, message, self) => {

    ma.push(Date.now(), sentiment.analyze(message).score);
    sentimentAverageScore = (ma.movingAverage().toFixed(2))
	console.log('Sentiment moving average score', sentimentAverageScore)
});

Closing off

So that is a very basic and simple way of calculating a sentiment score. Just keep in mind that this score does not relate to the context of what is being typed or that it can be used for anything sophisticated. It is just a simple and fun experiment during my holiday. For me, I used this score in a separate script for triggering different crowd noises on top of the stream in OBS. Just as a fun experiment and trying to get that stadium feel back that most of us haven’t had for the past 2 years at esports events… My last time was DreamHack Anaheim 2020.

In the following video you can see the script in action and if you want to try it yourself just tinker a little bit with the web-audio-player package. The dot indicates if the average sentiment is positive or negative.

Something to say?!