Skip to content

kapp.announces

Diffuser une annonce sur plusieurs canaux (chat, écran, voix, Discord…). Pluriel : kapp.announces. C'est une façade pratique au-dessus de chat / overlay / textToSpeech.

Service partagé appli + widget : API identique.

Quand l'utiliser (vs alternative)

  • Une annonce que le streamer a configurée dans tes préférencesplay('chemin.de.la.pref'). C'est le cas courant : lui choisit le contenu et les canaux, toi le moment.
  • Raccourcis simples : twitchChat, screenNotification, screenAnnounce, speech.
  • Pour cibler UN seul canal précis, tu peux aussi appeler directement le service dédié (kapp.chat.say, kapp.overlay.notification, kapp.textToSpeech.speech).
  • announce(data) = format riche multi-canal que TON appli fabrique (avancé, rarement nécessaire).

Méthodes

  • play(preference: string, tags = {}, title = null, metadata = {}): Promise<void> — joue l'annonce configurée par le streamer, désignée par le chemin de sa préférence. async.
  • twitchChat(message: string): Promise<void> — écrit dans le chat (= kapp.chat.say). async.
  • twitchAnnounce(message, color = 'primary'): Promise<void> — annonce Twitch colorée. async.
  • speech(message, moderate = false): Promise<void> — TTS (= kapp.textToSpeech.speech). async.
  • screenNotification(message, options = {}): Promise<void> — notification à l'écran. options: { duration?, html?, title?, title_html?, target?, visual? }. async.
  • screenAnnounce(message, options = {}): Promise<void> — grande annonce à l'écran. Mêmes options. async.
  • announce(data: AnnounceCreateData, tags = {}, title = null, metadata = {}): Promise<AnnounceModel> — annonce multi-canal fabriquée par l'appli. async.

Exemple (V2, exécutable)

js
// Le streamer a réglé une préférence `announces` nommée `messages.onWin` :
// c'est lui qui décide chat / écran / voix / Discord, l'appli dit juste « maintenant ».
await kapp.announces.play('messages.onWin', { user: 'Sam', amount: '250' });

await kapp.announces.screenNotification('Nouveau record battu !', {
    duration: 5,
    title: 'GG',
});

Deux façons de déclencher une annonce

play('chemin')announce({...})
D'où vient le contenudes réglages du streamer, lus en basede ton code
Scope à déclarerannounces:play, un seulun par track diffusée (chat:write, discord:message, dashboard-event:create…)
Track Discordfonctionne, le webhook reste côté serveuril faut fournir TON webhook

Lire la préférence puis la passer à announce() revient exactement au même que play() : la valeur porte sa référence, la plateforme la reconnaît. Ces deux lignes sont équivalentes — la seconde est juste plus explicite.

js
await kapp.announces.announce(kapp.preferences.get('messages.onWin'), { user: 'Sam' });
await kapp.announces.play('messages.onWin', { user: 'Sam' });

Tracks

Une annonce diffuse le même événement sur plusieurs « tracks », chacune activable indépendamment. La colonne « scope » ne concerne que announce({...}) : avec play(), un seul scope suffit (announces:play), puisque c'est le streamer qui a écrit le contenu.

TrackEffetChamp propreScope (payload libre)
chatMessagemessage dans le chat Twitchchat:write
chatAnnounceannonce Twitch coloréecolorchat:write
chatActionmessage /mechat:write
screenNotificationnotification à l'écranoptions
screenAnnouncegrande annonce à l'écranoptions
textToSpeechlu à voix haute
channelDashboardEventévénement dans le dashboard du streamerdashboard-event:create
discordmessage posté sur un webhook Discordwebhookdiscord:message
servicerelais vers des services d'appliservicesapp-service:call
  • Chaque track accepte des variations : une est tirée au sort, sinon on retombe sur messages.
  • channelDashboardEvent découpe le message : première ligne = titre, reste = corps.
  • discord ne part pas si aucun webhook n'est configuré.
  • Si aucune track n'est activée, l'annonce se replie sur k.channel.preferences.default_announce_tracks.
  • Une track qui échoue n'empêche pas les autres de se jouer.
  • Chat, annonce Twitch, /me et Discord attendent le stream_delay du channel ; les autres partent tout de suite.

Tags de message (#tag#)

Les tags que tu passes en 2e argument sont ajoutés à ceux que la plateforme fournit d'office. Un tag inconnu reste écrit en clair dans le message — c'est ainsi qu'on repère une faute de frappe plutôt que de perdre un bout de phrase.

TagContenu
#channel_name# / #channel_display_name#nom d'affichage du streamer
#channel_login#login Twitch
#currency_name# / #channel_currency_name#nom de la monnaie du channel
#currency_symbol# / #channel_currency_symbol#symbole de la monnaie
#command_symbol# / #channel_command_symbol#préfixe des commandes chat
#channel_language#langue du channel (fr / en)
#twitch_stream_title#titre du stream
#twitch_stream_category#catégorie Twitch en cours
#twitch_stream_chatters#nombre de chatteurs actifs
#twitch_stream_messages#messages échangés depuis le début du live
#twitch_stream_started_from#durée du live, 2h30m12s
#last_message#le message de base tiré pour cette annonce

Les deux conventions de nommage (#currency_name# et #channel_currency_name#) sont servies : elles viennent de deux moteurs historiques, les deux marchent.

#twitch_stream_started_at# n'existe plus. Il promettait une heure de début, que le serveur ne peut pas rendre correctement faute de fuseau horaire de channel — et il écrivait en réalité une durée absurde. Pour parler de l'ancienneté du live, utilise #twitch_stream_started_from#.

Habillage : le streamer décide, l'appli décrit

L'appli fournit le contenu de l'événement ; les couleurs, la police, la position et les animations viennent de l'habillage configuré par le streamer dans son dashboard. Il n'existe donc aucune option de style (accentColor, motion, variant…) : toute clé hors contrat est ignorée en silence côté serveur.

visual — joindre une image à l'événement

js
// Une image de la médiathèque du channel, désignée par son token (jamais une URL).
await kapp.announces.screenAnnounce('Nouveau palier atteint !', {
    visual: { type: 'image', source: 'channel-media', token: media.token, shape: 'circle' },
});

// Une image livrée avec l'appli, dans son dossier `public_assets`.
await kapp.announces.screenAnnounce('Victoire !', {
    visual: { type: 'image', source: 'app-asset', file: 'icons/trophy.png' },
});

// La photo de profil Twitch du viewer concerné.
await kapp.announces.screenNotification(`${user.displayName} vient de suivre !`, {
    visual: { type: 'profile', url: await user.getProfileImageUrl() },
});

Sources acceptées : channel-media, library-media (bibliothèque publique), app-asset (fichier de l'appli, chemin relatif à public_assets) et profile (CDN Twitch uniquement). Aucune URL externe n'est acceptée, quelle que soit la source.

Pour app-asset, c'est la version de l'appli installée sur le channel qui est servie : le chemin ne peut pas sortir de public_assets, et seules les images matricielles (png, jpg, jpeg, gif, webp, avif) sont acceptées — pas de SVG.

Un visuel non résolu — jeton inconnu, média d'un autre channel, URL externe, chemin de fichier hors contrat — est simplement retiré : le texte reste affiché.

target — dans quel overlay jouer

  • main (défaut) : l'overlay principal, même si l'appli tourne dans un overlay secondaire.
  • current : l'overlay qui héberge réellement l'appli, résolu côté serveur.

Une appli ne peut jamais désigner un overlay arbitraire. Si l'overlay ciblé n'est plus ouvert, l'appel échoue avec OVERLAY_NOT_FOUND — il n'y a pas de repli silencieux vers main.

Pièges

  • options.duration est en secondes (et non en millisecondes, contrairement à ce qu'indiquaient les anciennes versions de cette doc). Une valeur hors bornes est ramenée dans les clous : 1 à 180 s pour une annonce, 1 à 60 s pour une notification.
  • html: true reste supporté, mais le contenu est nettoyé avant affichage : la mise en forme passe, pas les scripts ni les gestionnaires d'événements.
  • announce() attend un objet AnnounceCreateData structuré — pour un simple texte, préfère screenNotification / screenAnnounce. Ses tracks screenNotification / screenAnnounce acceptent leurs propres options.
  • La diffusion est asynchrone. await veut dire « la plateforme a accepté », pas « c'est déjà à l'écran » : le délai de stream et l'enrichissement IA passent par une file côté serveur.
  • announce() ne rejette jamais (un refus part dans la console de l'overlay) ; play()rejette. Si tu veux réagir à un mauvais chemin ou un scope manquant, utilise play().
  • Le webhook Discord ne t'est jamais donné. Dans une préférence d'annonce, discord.webhook est un booléen (« le streamer en a configuré un, ou non »). Pour poster sur Discord avec ton propre webhook, il faut announce({...}) et le scope discord:message.
  • Ne modifie pas une préférence d'annonce avant de la jouer : elle porte une référence (_ref) et c'est la version en base qui sera diffusée, tes surcharges seront ignorées. Si tu veux vraiment décider du contenu, construis un objet littéral.
  • V1 mort : kapp.playAnnounceSet(...) n'existe plus.