Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Record Twitch Streams Automatically in Python
# This code is based on tutorial by slicktechies modified as needed to use oauth token from Twitch.
# You can read more details at: https://www.junian.net/2017/01/how-to-record-twitch-streams.html
# original code is from https://slicktechies.com/how-to-watchrecord-twitch-streams-using-livestreamer/
import requests
import os
import time
import json
import sys
import subprocess
import datetime
import getopt
class TwitchRecorder:
def __init__(self):
# global configuration
self.client_id = "jzkbprff40iqj646a697cyrvl0zt2m6" # don't change this
# get oauth token value by typing `streamlink --twitch-oauth-authenticate` in terminal
self.oauth_token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
self.ffmpeg_path = 'ffmpeg'
self.refresh = 30.0
self.root_path = "/Users/junian/Documents/twitch"
# user configuration
self.username = "juniantr"
self.quality = "best"
def run(self):
# path to recorded stream
self.recorded_path = os.path.join(self.root_path, "recorded", self.username)
# path to finished video, errors removed
self.processed_path = os.path.join(self.root_path, "processed", self.username)
# create directory for recordedPath and processedPath if not exist
if(os.path.isdir(self.recorded_path) is False):
os.makedirs(self.recorded_path)
if(os.path.isdir(self.processed_path) is False):
os.makedirs(self.processed_path)
# make sure the interval to check user availability is not less than 15 seconds
if(self.refresh < 15):
print("Check interval should not be lower than 15 seconds.")
self.refresh = 15
print("System set check interval to 15 seconds.")
# fix videos from previous recording session
try:
video_list = [f for f in os.listdir(self.recorded_path) if os.path.isfile(os.path.join(self.recorded_path, f))]
if(len(video_list) > 0):
print('Fixing previously recorded files.')
for f in video_list:
recorded_filename = os.path.join(self.recorded_path, f)
print('Fixing ' + recorded_filename + '.')
try:
subprocess.call([self.ffmpeg_path, '-err_detect', 'ignore_err', '-i', recorded_filename, '-c', 'copy', os.path.join(self.processed_path,f)])
os.remove(recorded_filename)
except Exception as e:
print(e)
except Exception as e:
print(e)
print("Checking for", self.username, "every", self.refresh, "seconds. Record with", self.quality, "quality.")
self.loopcheck()
def check_user(self):
# 0: online,
# 1: offline,
# 2: not found,
# 3: error
url = 'https://api.twitch.tv/kraken/streams/' + self.username
info = None
status = 3
try:
r = requests.get(url, headers = {"Client-ID" : self.client_id}, timeout = 15)
r.raise_for_status()
info = r.json()
if info['stream'] == None:
status = 1
else:
status = 0
except requests.exceptions.RequestException as e:
if e.response:
if e.response.reason == 'Not Found' or e.response.reason == 'Unprocessable Entity':
status = 2
return status, info
def loopcheck(self):
while True:
status, info = self.check_user()
if status == 2:
print("Username not found. Invalid username or typo.")
time.sleep(self.refresh)
elif status == 3:
print(datetime.datetime.now().strftime("%Hh%Mm%Ss")," ","unexpected error. will try again in 5 minutes.")
time.sleep(300)
elif status == 1:
print(self.username, "currently offline, checking again in", self.refresh, "seconds.")
time.sleep(self.refresh)
elif status == 0:
print(self.username, "online. Stream recording in session.")
filename = self.username + " - " + datetime.datetime.now().strftime("%Y-%m-%d %Hh%Mm%Ss") + " - " + (info['stream']).get("channel").get("status") + ".mp4"
# clean filename from unecessary characters
filename = "".join(x for x in filename if x.isalnum() or x in [" ", "-", "_", "."])
recorded_filename = os.path.join(self.recorded_path, filename)
# start streamlink process
subprocess.call(["streamlink", "--twitch-oauth-token", self.oauth_token, "twitch.tv/" + self.username, self.quality, "-o", recorded_filename])
print("Recording stream is done. Fixing video file.")
if(os.path.exists(recorded_filename) is True):
try:
subprocess.call([self.ffmpeg_path, '-err_detect', 'ignore_err', '-i', recorded_filename, '-c', 'copy', os.path.join(self.processed_path, filename)])
os.remove(recorded_filename)
except Exception as e:
print(e)
else:
print("Skip fixing. File not found.")
print("Fixing is done. Going back to checking..")
time.sleep(self.refresh)
def main(argv):
twitch_recorder = TwitchRecorder()
usage_message = 'twitch-recorder.py -u <username> -q <quality>'
try:
opts, args = getopt.getopt(argv,"hu:q:",["username=","quality="])
except getopt.GetoptError:
print (usage_message)
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print(usage_message)
sys.exit()
elif opt in ("-u", "--username"):
twitch_recorder.username = arg
elif opt in ("-q", "--quality"):
twitch_recorder.quality = arg
twitch_recorder.run()
if __name__ == "__main__":
main(sys.argv[1:])
@junian

This comment has been minimized.

Copy link
Owner Author

commented Jan 19, 2017

For complete tutorial and explanation about this gist, you can visit my blog post here: How to Record Twitch Streams Automatically in Python

@dannyvoid

This comment has been minimized.

Copy link

commented May 11, 2017

Possible to have it NOT record if it's a hosted stream?
It seems like that's the intended behavior, but on occasion, it actually does trigger a save during a hosted stream.

@ahmyboi

This comment has been minimized.

Copy link

commented Jun 13, 2017

Hi im experiencing issues. please help Here is my erro code:

File "C:\Users\Freddy\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 990, in _execute_child
startupinfo)
FileNotFoundError: [WinError 2] Das System kann die angegebene Datei nicht finden

it cant find a file, what file?

there have been many traceback errors or they relevant?

Checking for imaqtpie every 30.0 seconds. Record with best quality.
imaqtpie online. Stream recording in session.
Traceback (most recent call last):
File "C:\Users\Freddy\Desktop\TwitchMomentsGetter\twitch-recorder.py", line 148, in
main(sys.argv[1:])
File "C:\Users\Freddy\Desktop\TwitchMomentsGetter\twitch-recorder.py", line 145, in main
twitch_recorder.run()
File "C:\Users\Freddy\Desktop\TwitchMomentsGetter\twitch-recorder.py", line 65, in run
self.loopcheck()
File "C:\Users\Freddy\Desktop\TwitchMomentsGetter\twitch-recorder.py", line 112, in loopcheck
subprocess.call(["streamlink", "--twitch-oauth-token", self.oauth_token, "twitch.tv/" + self.username, self.quality, "-o", recorded_filename])
File "C:\Users\Freddy\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 267, in call
with Popen(*popenargs, **kwargs) as p:
File "C:\Users\Freddy\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 707, in init
restore_signals, start_new_session)

@oLaudix

This comment has been minimized.

Copy link

commented Jan 5, 2018

python twitch-recorder --user=geekandsundry
C:\Program Files\Python36\python.exe: can't open file 'twitch-recorder': [Errno 2] No such file or directory

python twitch-recorder.py --user=geekandsundry
Traceback (most recent call last):
File "twitch-recorder.py", line 5, in
import requests
ModuleNotFoundError: No module named 'requests'

Any idea why this is happening or how to fix it? I have streamlink and python installed but can't get it to work
Im on Windows.

@AlexanderEvans

This comment has been minimized.

Copy link

commented Jun 20, 2018

File "twitch-recorder.py", line 5, in import requests ModuleNotFoundError: No module named 'requests'
I am getting the same error, does anyone know how to fix it? I'm unfamiliar with python, I'm more knowledgeable about c style programming languages.

@nemsia

This comment has been minimized.

Copy link

commented Nov 9, 2018

to remove hosted channel, add this on line 111:
--twitch-disable-hosting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.