Skip to content

Commit

Permalink
Merge pull request #67 from offish/v1.6.4
Browse files Browse the repository at this point in the history
v1.6.4
  • Loading branch information
offish authored Jul 31, 2021
2 parents b912c39 + c01a2f7 commit b2b41cc
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 131 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ DATA = ["channel maskenissen"]

CLIENT_ID = "1hq8ektpki36w5kn37mluioungyqjo" # Twitch Client ID
OAUTH_TOKEN = "9f5einm9qtp0bj4m9l1ykevpwdn98o" # Twitch OAuth Token
PERIOD = "day" # day, week, month or all
PERIOD = 24 # day, week, month or all
LANGUAGE = "en" # en, es, th etc.
LIMIT = 100 # 1-100
...
Expand All @@ -53,7 +53,7 @@ while True:
video_length=10.5, # minutes as float
resolution=(1080, 1920), # height x width
frames=60,
period="day", # most viewed clips today
period=24, # most viewed clips today
)
sleep(24 * 60 * 60) # make a video daily
```
Expand All @@ -69,7 +69,7 @@ def make_video(
# twitch
client_id: str = CLIENT_ID,
oauth_token: str = OAUTH_TOKEN,
period: str = PERIOD,
period: int = PERIOD,
language: str = LANGUAGE,
limit: int = LIMIT,
# selenium
Expand Down
6 changes: 4 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def str_to_bool(value):
parser.add_argument("--check_version", type=str_to_bool, help="")
parser.add_argument("--client_id", type=str, help="")
parser.add_argument("--oauth_token", type=str, help="")
parser.add_argument("--period", type=str, help="")
parser.add_argument("--period", type=int, help="")
parser.add_argument("--language", type=str, help="")
parser.add_argument("--limit", type=int, help="")
parser.add_argument("--profile_path", type=str, help="")
Expand Down Expand Up @@ -74,4 +74,6 @@ def str_to_bool(value):
except Exception as e:
print(e)

make_video(**parameters)

if __name__ == "__main__":
make_video(**parameters)
2 changes: 1 addition & 1 deletion twitchtube/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__title__ = "twitchtube"
__author__ = "offish"
__license__ = "MIT"
__version__ = "1.6.3"
__version__ = "1.6.4"
31 changes: 26 additions & 5 deletions twitchtube/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,46 @@

import requests


local = locals()


def request(endpoint: str, headers: dict, params: dict) -> dict:
def request(endpoint: str, headers: dict, params: dict) -> requests.Response:
return requests.get(
"https://api.twitch.tv/" + endpoint, headers=headers, params=params
)


def data(slug: str, oauth_token: str, client_id: str) -> dict:
def data(slug: str, oauth_token: str, client_id: str) -> requests.Response:
return request(
"helix/clips",
{"Authorization": "Bearer " + oauth_token, "Client-Id": client_id},
{"id": slug},
)


def top_clips(headers: dict, params: dict) -> dict:
return request("kraken/clips/top", headers, params)
def game(game_list: list, oauth_token: str, client_id: str) -> requests.Response:
# returns data about every specified name of the game (including it's id)
# e.g. [Minecraft] -> {'id': '27471', 'name': 'Minecraft',
# 'box_art_url': 'https://static-cdn.jtvnw.net/ttv-boxart/Minecraft-{width}x{height}.jpg'}
return request(
"helix/games",
{"Authorization": "Bearer " + oauth_token, "Client-Id": client_id},
{"name": game_list}
)


def user(user_list: list, oauth_token: str, client_id: str) -> requests.Response:
# just like game() but for users
return request(
"helix/users",
{"Authorization": "Bearer " + oauth_token, "Client-Id": client_id},
{"login": user_list}
)


def top_clips(headers: dict, params: dict, oauth_token: str) -> requests.Response:
headers.update({"Authorization": "Bearer " + oauth_token})
return request("helix/clips", headers, params)


def get(name: str, **args) -> dict:
Expand All @@ -30,4 +50,5 @@ def get(name: str, **args) -> dict:
try:
return response.json()
except SyntaxError:
# probably should remove this, but i imagine it's for python2.7 support? dunno
return response
58 changes: 36 additions & 22 deletions twitchtube/clips.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
from math import ceil
from json import dump
import urllib.request
Expand All @@ -7,7 +8,6 @@
from .utils import format_blacklist, is_blacklisted
from .api import get


log = Log()


Expand Down Expand Up @@ -85,37 +85,47 @@ def download_clip(clip: str, basepath: str, oauth_token: str, client_id: str) ->
def get_clips(
blacklist: list,
category: str,
id_: str,
name: str,
path: str,
seconds: float,
ids: list,
client_id: str,
oauth_token: str,
period: str,
period: int,
language: str,
limit: int,
) -> (dict, list, list):
"""
Gets the top clips for given game, returns JSON response
from the Kraken API endpoint.
from the Helix API endpoint.
"""
data = {}
new_ids = []
new_titles = []

headers = {"Accept": "application/vnd.twitchtv.v5+json", "Client-ID": client_id}

params = {"period": period, "limit": limit}
params[category] = name

if language:
params["language"] = language
# params = {"period": period, "limit": limit}
params = {
"ended_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"started_at": (
datetime.datetime.now(datetime.timezone.utc)
- datetime.timedelta(hours=period)
).isoformat(),
"first": limit,
}

if category == "channel":
params["broadcaster_id"] = id_
else:
params["game_id"] = id_

log.info(f"Getting clips for {category} {name}")

response = get("top_clips", headers=headers, params=params)
response = get("top_clips", headers=headers, params=params, oauth_token=oauth_token)

if not response.get("clips"):
if not response.get("data"):
if response.get("error") == "Internal Server Error":
# the error is twitch's fault, we try again
get_clips(
Expand All @@ -134,33 +144,37 @@ def get_clips(

else:
log.warn(
f'Did not find "clips" in response {response} for {category} {name}, period: {period} language: {language}'
f'Did not find "data" in response {response} for {category} {name}, period: {period} language: {language}'
)

formatted_blacklist = format_blacklist(blacklist)
formatted_blacklist = format_blacklist(blacklist, oauth_token, client_id)

if "clips" in response:
for clip in response["clips"]:
tracking_id = clip["tracking_id"]
if "data" in response:
for clip in response["data"]:
clip_id = clip["id"]
duration = clip["duration"]

if seconds <= 0.0:
break

if not tracking_id in ids and not is_blacklisted(clip, formatted_blacklist):
data[clip["tracking_id"]] = {
"url": "https://clips.twitch.tv/" + clip["slug"],
if (
clip_id not in ids
and not is_blacklisted(clip, formatted_blacklist)
and (language == clip["language"] or not language)
):
data[clip["id"]] = {
"url": clip["url"],
"title": clip["title"],
"display_name": clip["broadcaster"]["display_name"],
"display_name": clip["broadcaster_name"],
"duration": duration,
}
new_ids.append(tracking_id)
new_ids.append(clip_id)
new_titles.append(clip["title"])
seconds -= duration

return (data, new_ids, new_titles)
return data, new_ids, new_titles

return ({}, [], [])
return {}, [], []


def download_clips(data: dict, path: str, oauth_token: str, client_id: str) -> list:
Expand Down
136 changes: 67 additions & 69 deletions twitchtube/config.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,67 @@
import pathlib

# Note:
# Changing FRAMES and or RESOULTION will heavily impact load on CPU.
# If you have a powerful enough computer you may set it to 1080p60

# other
PATH = str(pathlib.Path().absolute()).replace("\\", "/")
CLIP_PATH = PATH + "/clips/{}/{}"
CHECK_VERSION = (
True # see if youre running the latest version of twitchtube and opplast
)

DATA = ["c xQcOW", "c Trainwreckstv", "g Just Chatting"]
BLACKLIST = [
"c ludwig",
"g Pools, Hot Tubs, and Beaches",
] # channels/games you dont want to be included in the video

# twitch
CLIENT_ID = "" # Twitch Client ID
OAUTH_TOKEN = "" # Twitch OAuth Token
PERIOD = "day" # day, week, month or all
LANGUAGE = "en" # en, es, th etc.
LIMIT = 100 # 1-100


# selenium
ROOT_PROFILE_PATH = "" # Path to the Firefox profile where you are logged into YouTube
SLEEP = 3 # How many seconds Firefox should sleep for when uploading
HEADLESS = True # If True Firefox will be hidden (True/False)
DEBUG = True # If information when uploading should be printed (True/False)


# video options
RENDER_VIDEO = True # If clips should be rendered into one video (True/False). If set to False everything else under Video will be ignored
RESOLUTION = (
720,
1280,
) # Resoultion of the rendered video (height, width) for 1080p: ((1080, 1920))
FRAMES = 30 # Frames per second (30/60)
VIDEO_LENGTH = 10.5 # Minumum video length in minutes (doesn't always work)
RESIZE_CLIPS = True # Resize clips to fit RESOLUTION (True/False) If any RESIZE option is set to False the video might end up having a weird resolution
FILE_NAME = "rendered" # Name of the rendered video
ENABLE_INTRO = False # Enable (True/False)
RESIZE_INTRO = True # Resize (True/False) read RESIZE_CLIPS
INTRO_FILE_PATH = PATH + "/assets/intro.mp4" # Path to video file (str)
ENABLE_TRANSITION = True
RESIZE_TRANSITION = True
TRANSITION_FILE_PATH = PATH + "/assets/transition.mp4"
ENABLE_OUTRO = False
RESIZE_OUTRO = True
OUTRO_FILE_PATH = PATH + "/assets/outro.mp4"


# other options
SAVE_TO_FILE = True # If YouTube stuff should be saved to a separate file e.g. title, description & tags (True/False)
SAVE_FILE_NAME = "youtube" # Name of the file YouTube stuff should be saved to
UPLOAD_TO_YOUTUBE = True # If the rendered video should be uploaded to YouTube after rendering (True/False)
DELETE_CLIPS = True # If the downloaded clips should be deleted after rendering the video (True/False)


# youtube
TITLE = "" # youtube title, leave empty for the first clip's title
DESCRIPTION = (
"Streamers in this video:\n" # youtube description, streamers will be added
)
THUMBNAIL = "" # path to the image file to be set as thumbnail
TAGS = ["twitch", "just chatting", "xqc"] # your youtube tags
import pathlib

# Note:
# Changing FRAMES and or RESOLUTION will heavily impact load on CPU.
# If you have a powerful enough computer you may set it to 1080p60

# other
PATH = str(pathlib.Path().absolute()).replace("\\", "/")
CLIP_PATH = PATH + "/clips/{}/{}"
CHECK_VERSION = True # see if you're running the latest versions
DEBUG = True # If additional/debug information should be printed (True/False)

DATA = ["c xQcOW", "c Trainwreckstv", "g Just Chatting"]
BLACKLIST = [
"c ludwig",
"g Pools, Hot Tubs, and Beaches",
] # channels/games you dont want to be included in the video

# twitch
CLIENT_ID = "" # Twitch Client ID
OAUTH_TOKEN = "" # Twitch OAuth Token
PERIOD = 24 # how many hours since the clip's creation should've passed e.g. 24, 48 etc
LANGUAGE = "en" # en, es, th etc.
LIMIT = 100 # 1-100


# selenium
ROOT_PROFILE_PATH = r"" # Path to the Firefox profile where you are logged into YouTube
SLEEP = 3 # How many seconds Firefox should sleep for when uploading
HEADLESS = False # If True Firefox will be hidden (True/False)


# video options
RENDER_VIDEO = True # If clips should be rendered into one video (True/False). If set to False everything else under Video will be ignored
RESOLUTION = (
720,
1280,
) # Resoultion of the rendered video (height, width) for 1080p: ((1080, 1920))
FRAMES = 30 # Frames per second (30/60)
VIDEO_LENGTH = 10.5 # Minumum video length in minutes (doesn't always work)
RESIZE_CLIPS = True # Resize clips to fit RESOLUTION (True/False) If any RESIZE option is set to False the video might end up having a weird resolution
FILE_NAME = "rendered" # Name of the rendered video
ENABLE_INTRO = False # Enable (True/False)
RESIZE_INTRO = True # Resize (True/False) read RESIZE_CLIPS
INTRO_FILE_PATH = PATH + "/twitchtube/files/intro.mp4" # Path to video file (str)
ENABLE_TRANSITION = True
RESIZE_TRANSITION = True
TRANSITION_FILE_PATH = PATH + "/twitchtube/files/transition.mp4"
ENABLE_OUTRO = False
RESIZE_OUTRO = True
OUTRO_FILE_PATH = PATH + "/twitchtube/files/outro.mp4"


# other options
SAVE_TO_FILE = True # If YouTube stuff should be saved to a separate file e.g. title, description & tags (True/False)
SAVE_FILE_NAME = "youtube" # Name of the file YouTube stuff should be saved to
UPLOAD_TO_YOUTUBE = True # If the rendered video should be uploaded to YouTube after rendering (True/False)
DELETE_CLIPS = True # If the downloaded clips should be deleted after rendering the video (True/False)


# youtube
TITLE = "" # youtube title, leave empty for the first clip's title
DESCRIPTION = (
"Streamers in this video:\n" # youtube description, streamers will be added
)
THUMBNAIL = "" # path to the image file to be set as thumbnail
TAGS = ["twitch", "just chatting", "xqc"] # your youtube tags
1 change: 1 addition & 0 deletions twitchtube/files/logs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

File renamed without changes.
Loading

0 comments on commit b2b41cc

Please sign in to comment.