Twitch Channel Points Integration . AutoHotkey
Keyboard Input
By triggering keyboard input your viewers can influence, help or sabotage your gameplay – for example throw a grenade or activate a skill at the most inconvenient time.
Trigger Hotkeys
Your viewers become technical assistants to your stream: Hotkeys in your broadcasting software show and hide sources, change scenes, display thematic overlays or funny gifs.
Play Audio
Viewers are able to trigger your custom audio files – for example a sad violin when you have died live on stream, a round of applause when winning, or a classic quack sound whenever.
Text-to-Speech (TTS)
Give your viewers a voice! They can enter custom text in the Twitch Reward (up to 500 characters) and have Google voice read it aloud in your specified language 7777777777777
tcpi.ahk.tcpi.ahk. Chatty must run in the background, or you can use it to keep track of Twitchchat.tcpi.ahk file in a text editor (like notepad.exe)..ahk.
Get in touch with Myian on Discord, Twitter, or Twitch.
Always fresh from GitHub.
; SCRIPT INFORMATION ============================================================================================================
;
; Script Name: Twitch Channel Points Integration (tcpi)
; Description: Redeeming Channel Points on Twitch sends key input to your game, broadcasting software, or plays a sound file
; Filename: tcpi.ahk
; Script Version: v0.73
; Modified: 2020-07-22
; AHK Version: v1.1.24.01 - August 2, 2016
; Author: Myian <heymyian@gmail.com> <https://twitch.tv/myian>
;
;
;
; INSTRUCTIONS ==================================================================================================================
;
; 1) AutoHotkey -----------------------------------------------------------------------------------------------------------------
;
; Download AutoHotkey here: https://www.autohotkey.com/ and install.
; Run this script as administrator. It's now in your system tray.
; Script needs to be restarted after midnight (right click on the icon in system tray > Reload This Script)
;
;
; 2) Chatty ---------------------------------------------------------------------------------------------------------------------
;
; This script is configured to be used with Chatty logfiles. Download Chatty here: https://chatty.github.io/
; Chatty must run on your computer and it must have "Log to file" enabled. You find the settings here:
; Main > Settings > Chat > Log to file
;
; 1. Add only your channel to the list of channels to be logged
; 2. Select a folder where the log files should be saved
; 3. In the column for "Message Types", at least "Chat Info" needs to be selected
; 4. Unselect everything else if you don't need chat logs otherwise and want the most lightweight script
; 5. Split Logs: Daily (file size might grow too large otherwise. No need to restart at midnight if other option is chosen)
; 6. Uncheck "Lock files", otherwise AutoHotkey can't read the file
; 7. Timestamp: [2020-01-26 13:56:33]
;
;
; 3) Variables ------------------------------------------------------------------------------------------------------------------
;
; Change these variables to match your environment:
;
logfolder := "O:\Stream\logs" ; The folder where your log files are stored. Last modified file is used
soundfolder := "O:\Stream\soundbits" ; The folder where your sound files are stored
ttsfile := "O:\Stream\tts.mp3" ; Path where you want your text-to-speech file to sit
ttslang := "en" ; Text-to-speech language code (en, es, de, nl, ...)
game := "PlanetSide2_x64.exe" ; Your game's exe file name (not path!)
checktime := 200 ; Time in milliseconds until the log file is checked for changes again
; The script only ever reads the last log line, so keep this number fairly low
; For this reason, there also is no "reward action queue"
;
;
; 4) Twitch Rewards -------------------------------------------------------------------------------------------------------------
;
; name: "string"
; Name of your reward exactly as it appears on Twitch
;
; type: game | "globaltrigger" | "tts"
;
; game
; Reward's actions will only trigger while the game is active to prevent unwanted keyboard input
; It's a variable. Set your game's exe under point 3)
; Reward's sound will always trigger
;
; "globaltrigger"
; Reward's actions and sound will always trigger
; Meant for sound rewards and broadcasting software hotkeys
; The according hotkeys have to be set up in your broadcasting software as well
;
; "tts"
; Text-to-speech
; This requires "Viewer to Enter Text" in Twitch
;
; sound: "string.mp3"
; Name of the sound file you want to be played
; In some cases, the sound file will not play no matter what. Try saving the file at lower bitrate
; There is no volume control per sound file. Sounds tend to come out too loud
; Either save the sound file at the according volume, or lower the ahk output volume in Windows Volume Mixer
;
; actions: "{AHK key}" | "Sleep, duration"
; Actions to be performed, in the order given
; List of Keys: https://www.autohotkey.com/docs/KeyList.htm
; Modifier keys (^ Ctrl, ! Alt, + Shift) tend to not work right, so send the actual keys individually instead
; If a sequence of keys is seemingly not accepted, "Sleep, 50" (50ms pause) between key presses might help
rewards := []
rewards[0,"name"] := "PS2 :: Granada"
rewards[0,"type"] := game
rewards[0,"sound"] := "granada.mp3"
rewards[0,"actions"]:= [ "{MButton}" ]
rewards[1,"name"] := "PS2 :: Tool Slot"
rewards[1,"type"] := game
rewards[1,"sound"] := "boing.mp3"
rewards[1,"actions"]:= [ "{3}", "Sleep, 1500", "{LButton}" ]
rewards[2,"name"] := "PS2 :: v5"
rewards[2,"type"] := game
rewards[2,"actions"]:= [ "{v}", "Sleep, 50", "{5}" ]
rewards[3,"name"] := "PS2 :: Instant Action"
rewards[3,"type"] := game
rewards[3,"actions"]:= [ "!{i}" ]
rewards[4,"name"] := "Stream :: Rainbow"
rewards[4,"type"] := "globaltrigger"
rewards[4,"sound"] := "chime.mp3"
rewards[4,"actions"]:= [ "{Ctrl down}", "Sleep, 50", "{Numpad8 down}", "Sleep, 50", "{Ctrl up}", "Sleep, 50", "{Numpad8 up}"
, "Sleep, 10000", "{Ctrl down}", "Sleep, 50", "{Numpad8 down}", "Sleep, 50", "{Ctrl up}", "Sleep, 50", "{Numpad8 up}" ]
rewards[5,"name"] := "Stream :: Sad"
rewards[5,"type"] := "globaltrigger"
rewards[5,"sound"] := "sad2.mp3"
rewards[5,"actions"] := [ "{Ctrl down}", "Sleep, 50", "{Numpad7 down}", "Sleep, 50", "{Ctrl up}", "Sleep, 50", "{Numpad7 up}"
, "Sleep, 10000", "{Ctrl down}", "Sleep, 50", "{Numpad9 down}", "Sleep, 50", "{Ctrl up}", "Sleep, 50", "{Numpad9 up}" ]
rewards[6,"name"] := "PS2 :: F"
rewards[6,"type"] := game
rewards[6,"sound"] := "boing.mp3"
rewards[6,"actions"] := [ "{F}" ]
rewards[7,"name"] := "TTS"
rewards[7,"type"] := "tts"
; ===============================================================================================================================
; ===============================================================================================================================
;
; Only change the code from here if you know what you are doing
; Some comments are provided to explain what is going on
;
; ===============================================================================================================================
; ===============================================================================================================================
#Persistent
#SingleInstance Force
#NoEnv
#Warn
SendMode Input
filesize1 := ""
filesize2 := ""
Time := ""
; get last modified, presumably current, log file in the folder
Loop %logfolder%\*.*
If ( A_LoopFileTimeModified >= Time )
Time := A_LoopFileTimeModified, logfile := A_LoopFileLongPath
; get this file's size in bits
FileGetSize, filesize1, %logfile%
; do the thing
SetTimer, checkfile, %checktime%
Return
; the thing
checkfile:
; get file size again, stored in different variable
FileGetSize, filesize2, %logfile%
; compare the file sizes. if they differ, the file has been updated since the last check
If(filesize1 != filesize2) {
filesize1 := filesize2
; get last line
Loop, read, %logfile%
{
lastline := A_LoopReadLine
}
; change this line if you use a different timestamp format or a different chat logger altogether
; this checks if the 23rd character is an opening bracket. look at your chatlog file to understand why
If (SubStr(lastline,23,2)="[P") {
; cycle through each reward in the array
For Each, reward in rewards {
; do the thing where the reward name matches the last line
If (InStr(lastline, reward.name)) {
; in case a sound file is specified, play that.
If (reward.sound!="") {
;SoundPlay, % soundfolder . "\" . reward.sound, Wait
SoundPlay, % soundfolder . "\" . reward.sound
}
; in case there are actions specified
If (reward.actions!="") {
; game must be focused, or it's a hotkey for broadcasting software
If (((reward.type=game)&&(WinActive("ahk_exe" . game))) or (reward.type="globaltrigger")) {
; cycle through the actions
For Each, action in reward.actions {
; sleep between keys, sometimes important for applications to pick up input
If InStr(action,"Sleep,") {
el_sleep := StrSplit(action, ",")
Sleep, el_sleep[2]
}
; keypress
Else {
SendInput, % action
}
}
}
}
; in case the thing is tts
If (reward.type=="tts") {
tts := lastline
; gets the viewer input after ) [
; maximum length as per Twitch for viewer input is 500 characters
; maximum length as per Google Translate for one mp3 is 200 characters
; separates the result in groups of max. 200 characters separated by punctuation or whitespace
; if there is neither punctuation nor whitespace within 167 characters, the matching fails and there is no output
; (cost) (separate by punctuation |or whitespace )(repeat x2 )
RegExMatch(tts, "\(\d+\)\s\[(.{167,200}(?=[.,?!;\""])|.{0,200}(?=[\s\/]|]))((?1))((?1))", tts)
; download the file to the specified path and play it
UrlDownloadToFile, https://translate.google.com/translate_tts?ie=UTF-8&tl=%ttslang%&client=tw-ob&q=%tts1%, %ttsfile%
Soundplay, %ttsfile%, Wait
; if the viewer input is longer than 200 characters, download and play the other parts
If (tts2!="") {
UrlDownloadToFile, https://translate.google.com/translate_tts?ie=UTF-8&tl=%ttslang%&client=tw-ob&q=%tts2%, %ttsfile%
Soundplay, %ttsfile%, Wait
}
If (tts3!="") {
UrlDownloadToFile, https://translate.google.com/translate_tts?ie=UTF-8&tl=%ttslang%&client=tw-ob&q=%tts3%, %ttsfile%
Soundplay, %ttsfile%, Wait
}
}
}
}
}
}
Return