Dans ce tutoriel, je vous propose de découvrir comment créer un tchat personnalisé pour Twitch en CSS.
OBS intègre un navigateur web
Pour streamer sur Twitch la plupart du temps, on utilise le logiciel Open Broadcaster Software qui permet de gérer des scènes avec différents calques. Il est possible d'utiliser différentes sources sur ces calques et il est même possible d'utiliser une page web comme source. Pour créer un tchat personnalisé, il nous suffira donc de créer une simple page web qui récupère les derniers messages envoyés sur le tchat.
Pour récupérer ces messages, il est possible d'utiliser la version IRC du tchat Twitch avec tmi.js par exemple ou d'utiliser un service tiers comme StreamElements.
Pourquoi StreamElements ?
StreamElements permet de gérer un overlay de manière visuelle et génère une page web que l'on peut ensuite utiliser comme calque OBS. Il dispose déjà d'un widget de tchat, mais qui n'est pas suffisamment personnalisable, mais il est possible de créer un widget HTML personnalisé dans lequel on peut ajouter de l'HTML, du CSS et du JavaScript.
Dans le cadre de ces widgets, il faudra écouter l'évènement onEventReceived
qui sera appelé lors de différents évènements liés à Twitch (et aux autres services supportés). Dans notre cas, on ne s'intéresse qu'aux messages.
window.addEventListener('onEventReceived', function (obj) {
// On gère la suppression de messages
if (obj.detail.listener === "delete-message") {
return removeFromDom(`#msg-${obj.detail.event.msgId}`);
} else if (obj.detail.listener === "delete-messages") {
const sender = obj.detail.event.userId;
return removeFromDom(`.message[data-sender=${sender}]`);
}
// On filtre certains message
if (obj.detail.listener !== "message") return;
let data = obj.detail.event.data;
if (data.text.startsWith("!") && hideCommands) {
return;
}
// On ajoute le message au DOM
addMessage(data, obj.detail.event.renderedText)
})
Le reste du code consiste à manipuler le DOM pour injecter nos messages au fur et à mesure.
const limit = 20
function addMessage (data, html) {
const userColor = data.displayColor || `#${md5(data.displayName).substr(26)}`
const badges = data.badges.reduce((acc, badge) => acc + `<img alt="" src="${badge.url}" class="badge">`,'')
// const html = attachEmotes(data)
const message= `<div data-sender="${data.userId}" id="msg-${data.msgId}" class="message">
<div class="meta">
<span class="badges">${badges}</span>
<span class="name" style="--color: ${userColor}">${data.displayName}</span>
</div>
<div class="content">
${html}
</div>
</div>`
chatBox.insertAdjacentHTML('beforeend', message)
// On limite le nbre de message pour ne pas surcharger le rendu
const messages = document.querySelectorAll('.message')
const messageCount = messages.length
if (messageCount > limit) {
Array.from(messages).slice(0, messageCount - limit).forEach((el) => {
el.remove()
})
}
}
Enfin, la partie CSS dépendra du style que vous souhaitez obtenir. Pour s'assurer d'avoir toujours le dernier message en bas de l'écran, on utilisera une position absolute et une grille pour espacer chaque message.
.messages {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
display: grid;
grid-template-columns: 1fr;
gap: 0.5rem;
}
.message {
/* A vous de jouer ;) */
}