From 637e4c66f28da2dec6feec29f16e36774b329962 Mon Sep 17 00:00:00 2001 From: liamb Date: Sat, 15 Apr 2023 17:20:52 +1000 Subject: [PATCH 01/26] adds zoom function --- utils/.config.template.toml | 1 + video_creation/screenshot_downloader.py | 34 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/utils/.config.template.toml b/utils/.config.template.toml index b2fa1d4..e6fa558 100644 --- a/utils/.config.template.toml +++ b/utils/.config.template.toml @@ -31,6 +31,7 @@ storymodemethod= { optional = true, default = 1, example = 1, explanation = "Sty storymode_max_length = { optional = true, default = 1000, example = 1000, explanation = "Max length of the storymode video in characters. 200 characters are approximately 50 seconds.", type = "int", nmin = 1, oob_error = "It's very hard to make a video under a second." } resolution_w = { optional = false, default = 1080, example = 1440, explantation = "Sets the width in pixels of the final video" } resolution_h = { optional = false, default = 1920, example = 2560, explantation = "Sets the height in pixels of the final video" } +zoom = { optional = true, default = 1, example = 1.1, explanation = "Sets the browser zoom level. Useful if you want the text larger.", type = "float", nmin = 0.1, nmax = 2, oob_error = "The text is really difficult to read at a zoom level higher than 2" } [settings.background] background_choice = { optional = true, default = "minecraft", example = "rocket-league", options = ["minecraft", "gta", "rocket-league", "motor-gta", "csgo-surf", "cluster-truck", "minecraft-2","multiversus","fall-guys","steep", ""], explanation = "Sets the background for the video based on game name" } diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 1c3ab5e..ecff2f4 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -158,9 +158,20 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): postcontentpath = f"assets/temp/{reddit_id}/png/title.png" try: - page.locator('[data-test-id="post-content"]').screenshot( - path=postcontentpath - ) + if(settings.config["settings"]["zoom"] != 1): + # store zoom settings + zoom = settings.config["settings"]["zoom"] + # zoom the body of the page + page.evaluate("document.body.style.zoom="+str(zoom)) + # as zooming the body doesn't change the properties of the divs, we need to adjust for the zoom + location = page.locator('[data-test-id="post-content"]').bounding_box() + for i in location: + location[i] = float("{:.2f}".format(location[i]*zoom)) + page.screenshot(clip=location, path=postcontentpath) + else: + page.locator('[data-test-id="post-content"]').screenshot( + path=postcontentpath + ) except Exception as e: print_substep("Something went wrong!", style="red") resp = input( @@ -214,9 +225,20 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): [comment_tl, comment["comment_id"]], ) try: - page.locator(f"#t1_{comment['comment_id']}").screenshot( - path=f"assets/temp/{reddit_id}/png/comment_{idx}.png" - ) + if(settings.config["settings"]["zoom"] != 1): + # store zoom settings + zoom = settings.config["settings"]["zoom"] + # zoom the body of the page + page.evaluate("document.body.style.zoom="+str(zoom)) + # as zooming the body doesn't change the properties of the divs, we need to adjust for the zoom + location = page.locator(f"#t1_{comment['comment_id']}").bounding_box() + for i in location: + location[i] = float("{:.2f}".format(location[i]*zoom)) + page.screenshot(clip=location, path=f"assets/temp/{reddit_id}/png/comment_{idx}.png") + else: + page.locator(f"#t1_{comment['comment_id']}").screenshot( + path=f"assets/temp/{reddit_id}/png/comment_{idx}.png" + ) except TimeoutError: del reddit_object["comments"] screenshot_num += 1 From d19dfac8a353175849d2a84720e6001983ca4d05 Mon Sep 17 00:00:00 2001 From: liamb Date: Fri, 5 May 2023 11:21:06 +1000 Subject: [PATCH 02/26] adds elevenlabs --- TTS/elevenlabs.py | 46 +++++++++++++++++++++++++++++++++++++ requirements.txt | 3 ++- utils/.config.template.toml | 4 +++- video_creation/voices.py | 2 ++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 TTS/elevenlabs.py diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py new file mode 100644 index 0000000..4a7bfd2 --- /dev/null +++ b/TTS/elevenlabs.py @@ -0,0 +1,46 @@ +import random + +from elevenlabs import generate, save + +from utils import settings + + +class elevenlabs: + def __init__(self): + self.max_chars = 5000 + self.voices = ["Adam", "Antoni", "Arnold", "Bella", "Domi", "Elli", "Josh", "Rachel", "Sam"] + + def run( + self, + text: str, + filepath: str, + random_voice=False, + ): + voice_name = settings.config["settings"]["tts"]["elevenlabs_voice_name"] + if voice_name == "": + voice_name = "Bella" + raise ValueError( + "set elevenlabs name value to a valid value, switching to default voice (Bella)" + ) + if random_voice: + voice_name = self.randomvoice() + + if settings.config["settings"]["tts"]["elevenlabs_api_key"]: + api_key = settings.config["settings"]["tts"]["elevenlabs_api_key"] + else: + api_key = None + print("set elevenlabs api key value to a valid value or quota will be limited") + + audio = generate( + api_key=api_key, + text=text, + voice=voice_name, + model="eleven_monolingual_v1" + ) + save( + audio=audio, + filename=f"{filepath}" + ) + + def randomvoice(self): + return random.choice(self.voices) diff --git a/requirements.txt b/requirements.txt index 22d3d7f..88f4f45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,4 +19,5 @@ unidecode==1.3.2 spacy==3.4.1 torch==1.12.1 transformers==4.25.1 -ffmpeg-python==0.2.0 \ No newline at end of file +ffmpeg-python==0.2.0 +elevenlabs==0.2.10 \ No newline at end of file diff --git a/utils/.config.template.toml b/utils/.config.template.toml index b2fa1d4..58ff86e 100644 --- a/utils/.config.template.toml +++ b/utils/.config.template.toml @@ -42,7 +42,9 @@ background_thumbnail_font_size = { optional = true, type = "int", default = 96, background_thumbnail_font_color = { optional = true, default = "255,255,255", example = "255,255,255", explanation = "Font color in RGB format for the thumbnail text" } [settings.tts] -voice_choice = { optional = false, default = "tiktok", options = ["streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. This can be left blank and you will be prompted to choose at runtime." } +voice_choice = { optional = false, default = "tiktok", options = ["elevenlabs", "streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. This can be left blank and you will be prompted to choose at runtime." } +elevenlabs_voice_name = { optional = false, default = "Bella", example = "Bella", explanation = "The voice used for elevenlabs" } +elevenlabs_api_key = { optional = true, example = "21f13f91f54d741e2ae27d2ab1b99d59", explanation = "Elevenlabs API key" } aws_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for AWS Polly" } streamlabs_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for Streamlabs Polly" } tiktok_voice = { optional = true, default = "en_us_001", example = "en_us_006", explanation = "The voice used for TikTok TTS" } diff --git a/video_creation/voices.py b/video_creation/voices.py index 425f589..cd75f06 100644 --- a/video_creation/voices.py +++ b/video_creation/voices.py @@ -7,6 +7,7 @@ from TTS.TikTok import TikTok from TTS.aws_polly import AWSPolly from TTS.engine_wrapper import TTSEngine from TTS.pyttsx import pyttsx +from TTS.elevenlabs import elevenlabs from TTS.streamlabs_polly import StreamlabsPolly from utils import settings from utils.console import print_table, print_step @@ -19,6 +20,7 @@ TTSProviders = { "StreamlabsPolly": StreamlabsPolly, "TikTok": TikTok, "pyttsx": pyttsx, + "ElevenLabs": elevenlabs } From 066f657134cccc50fed23f9877f9053412253744 Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sat, 6 May 2023 04:17:48 +1000 Subject: [PATCH 03/26] Update TTS/elevenlabs.py Co-authored-by: Simon <65854503+OpenSourceSimon@users.noreply.github.com> --- TTS/elevenlabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index 4a7bfd2..837ddc9 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -29,7 +29,7 @@ class elevenlabs: api_key = settings.config["settings"]["tts"]["elevenlabs_api_key"] else: api_key = None - print("set elevenlabs api key value to a valid value or quota will be limited") + print("You didn't set an Elevenlabs API key! Trying without API key, but you'll probably hit an error.") audio = generate( api_key=api_key, From facae5efd5df77afacb5e48f7080fa09260ae0ce Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sat, 6 May 2023 04:18:48 +1000 Subject: [PATCH 04/26] Update utils/.config.template.toml Co-authored-by: Simon <65854503+OpenSourceSimon@users.noreply.github.com> --- utils/.config.template.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/.config.template.toml b/utils/.config.template.toml index 58ff86e..aadedd2 100644 --- a/utils/.config.template.toml +++ b/utils/.config.template.toml @@ -42,7 +42,7 @@ background_thumbnail_font_size = { optional = true, type = "int", default = 96, background_thumbnail_font_color = { optional = true, default = "255,255,255", example = "255,255,255", explanation = "Font color in RGB format for the thumbnail text" } [settings.tts] -voice_choice = { optional = false, default = "tiktok", options = ["elevenlabs", "streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. This can be left blank and you will be prompted to choose at runtime." } +voice_choice = { optional = false, default = "tiktok", options = ["elevenlabs", "streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. " } elevenlabs_voice_name = { optional = false, default = "Bella", example = "Bella", explanation = "The voice used for elevenlabs" } elevenlabs_api_key = { optional = true, example = "21f13f91f54d741e2ae27d2ab1b99d59", explanation = "Elevenlabs API key" } aws_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for AWS Polly" } From 685f8c4ddd4cf8e1e630ced3e8d1085010e2c9c8 Mon Sep 17 00:00:00 2001 From: liamb Date: Sat, 6 May 2023 04:35:29 +1000 Subject: [PATCH 05/26] format like other tts engines --- TTS/elevenlabs.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index 837ddc9..03c8aff 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -4,26 +4,34 @@ from elevenlabs import generate, save from utils import settings +voices = [ + "Adam", + "Antoni", + "Arnold", + "Bella", + "Domi", + "Elli", + "Josh", + "Rachel", + "Sam", +] class elevenlabs: def __init__(self): self.max_chars = 5000 - self.voices = ["Adam", "Antoni", "Arnold", "Bella", "Domi", "Elli", "Josh", "Rachel", "Sam"] + self.voices = voices - def run( - self, - text: str, - filepath: str, - random_voice=False, - ): - voice_name = settings.config["settings"]["tts"]["elevenlabs_voice_name"] - if voice_name == "": - voice_name = "Bella" - raise ValueError( - "set elevenlabs name value to a valid value, switching to default voice (Bella)" - ) + def run(self, text, filepath, random_voice: bool = False): if random_voice: - voice_name = self.randomvoice() + voice = self.randomvoice() + else: + if not settings.config["settings"]["tts"]["elevenlabs_voice_name"]: + print(f"Please set the config variable ELEVENLABS_VOICE_NAME to a valid voice. options are: {voices}. Using random voice.") + voice = self.randomvoice() + else: + voice = str( + settings.config["settings"]["tts"]["elevenlabs_voice_name"] + ).capitalize() if settings.config["settings"]["tts"]["elevenlabs_api_key"]: api_key = settings.config["settings"]["tts"]["elevenlabs_api_key"] @@ -34,7 +42,7 @@ class elevenlabs: audio = generate( api_key=api_key, text=text, - voice=voice_name, + voice=voice, model="eleven_monolingual_v1" ) save( From 815c4b2a2e4eb8d9ceea924ffae3248a4d2be26f Mon Sep 17 00:00:00 2001 From: liamb Date: Sat, 6 May 2023 04:37:16 +1000 Subject: [PATCH 06/26] throw error on no api --- TTS/elevenlabs.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index 03c8aff..2da8e8e 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -36,8 +36,9 @@ class elevenlabs: if settings.config["settings"]["tts"]["elevenlabs_api_key"]: api_key = settings.config["settings"]["tts"]["elevenlabs_api_key"] else: - api_key = None - print("You didn't set an Elevenlabs API key! Trying without API key, but you'll probably hit an error.") + raise ValueError( + "You didn't set an Elevenlabs API key! Please set the config variable ELEVENLABS_API_KEY to a valid API key." + ) audio = generate( api_key=api_key, From 838333160dd854f3b2e428e32b2999bac016d9b1 Mon Sep 17 00:00:00 2001 From: Josh Holly Date: Mon, 8 May 2023 07:12:27 -0500 Subject: [PATCH 07/26] Update final_video.py Fixed opacity so comments will have transparency if the user sets the "opacity" option below 1. --- video_creation/final_video.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 4838574..909c149 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -120,6 +120,7 @@ def make_final_video( # settings values W: Final[int] = int(settings.config["settings"]["resolution_w"]) H: Final[int] = int(settings.config["settings"]["resolution_h"]) + opacity = int(settings.config["settings"]["opacity"]) reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) print_step("Creating the final video 🎥") @@ -242,8 +243,9 @@ def make_final_video( "v" ].filter("scale", screenshot_width, -1) ) + image_overlay = image_clips[i].filter("colorchannelmixer", aa=opacity) background_clip = background_clip.overlay( - image_clips[i], + image_overlay, enable=f"between(t,{current_time},{current_time + audio_clips_durations[i]})", x="(main_w-overlay_w)/2", y="(main_h-overlay_h)/2", @@ -346,8 +348,8 @@ def make_final_video( old_percentage = pbar.n pbar.update(100 - old_percentage) pbar.close() - - save_data(subreddit, filename + ".mp4", title, idx, background_config[2]) + path = r"~/Library/Mobile Documents/com~apple~CloudDocs/reddit/" + save_data(path+subreddit, filename + ".mp4", title, idx, background_config[2]) print_step("Removing temporary files 🗑") cleanups = cleanup(reddit_id) print_substep(f"Removed {cleanups} temporary files 🗑") From 473dacdbfc26d72302228eb2d16fdf92bb6ec06d Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sat, 13 May 2023 10:31:02 +1000 Subject: [PATCH 08/26] Update elevenlabs.py --- TTS/elevenlabs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index 2da8e8e..af5dbec 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -18,7 +18,7 @@ voices = [ class elevenlabs: def __init__(self): - self.max_chars = 5000 + self.max_chars = 2500 self.voices = voices def run(self, text, filepath, random_voice: bool = False): @@ -48,7 +48,7 @@ class elevenlabs: ) save( audio=audio, - filename=f"{filepath}" + filename=filepath ) def randomvoice(self): From 270e725e4083918b15f4624624cc6a104ae9ad65 Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sun, 21 May 2023 20:42:12 +1000 Subject: [PATCH 09/26] Update TTS/elevenlabs.py Co-authored-by: Simon <65854503+OpenSourceSimon@users.noreply.github.com> --- TTS/elevenlabs.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index af5dbec..e24873b 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -25,9 +25,6 @@ class elevenlabs: if random_voice: voice = self.randomvoice() else: - if not settings.config["settings"]["tts"]["elevenlabs_voice_name"]: - print(f"Please set the config variable ELEVENLABS_VOICE_NAME to a valid voice. options are: {voices}. Using random voice.") - voice = self.randomvoice() else: voice = str( settings.config["settings"]["tts"]["elevenlabs_voice_name"] From 51d0486866d1d52f15444f45ae998b3d686f75aa Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sun, 21 May 2023 20:42:23 +1000 Subject: [PATCH 10/26] Update TTS/elevenlabs.py Co-authored-by: Simon <65854503+OpenSourceSimon@users.noreply.github.com> --- TTS/elevenlabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index e24873b..f427c07 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -41,7 +41,7 @@ class elevenlabs: api_key=api_key, text=text, voice=voice, - model="eleven_monolingual_v1" + model="eleven_multilingual_v1" ) save( audio=audio, From 9a90363f5672dfb17d2eb87e54b4d86afa1c5abb Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sun, 21 May 2023 20:42:34 +1000 Subject: [PATCH 11/26] Update utils/.config.template.toml Co-authored-by: Simon <65854503+OpenSourceSimon@users.noreply.github.com> --- utils/.config.template.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/.config.template.toml b/utils/.config.template.toml index aadedd2..502406b 100644 --- a/utils/.config.template.toml +++ b/utils/.config.template.toml @@ -43,7 +43,7 @@ background_thumbnail_font_color = { optional = true, default = "255,255,255", ex [settings.tts] voice_choice = { optional = false, default = "tiktok", options = ["elevenlabs", "streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. " } -elevenlabs_voice_name = { optional = false, default = "Bella", example = "Bella", explanation = "The voice used for elevenlabs" } +elevenlabs_voice_name = { optional = false, default = "Bella", example = "Bella", explanation = "The voice used for elevenlabs", options = ["Adam", "Antoni", "Arnold", "Bella", "Domi", "Elli", "Josh", "Rachel", "Sam", ] } elevenlabs_api_key = { optional = true, example = "21f13f91f54d741e2ae27d2ab1b99d59", explanation = "Elevenlabs API key" } aws_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for AWS Polly" } streamlabs_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for Streamlabs Polly" } From 15a17896cadb0cef707060346d6cfc4d1a5918e8 Mon Sep 17 00:00:00 2001 From: Josh Holly Date: Sun, 21 May 2023 07:41:21 -0500 Subject: [PATCH 12/26] Remoted int() wrapper Removed int() around opacity = settings.config["settings"]["opacity"] to fraction numbers (IE 0.5, 0.7, etc) --- video_creation/final_video.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 11804c6..7418931 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -142,7 +142,8 @@ def make_final_video( # settings values W: Final[int] = int(settings.config["settings"]["resolution_w"]) H: Final[int] = int(settings.config["settings"]["resolution_h"]) - opacity = int(settings.config["settings"]["opacity"]) + """Fixed to allow fraction opacity Ea: 0.7""" + opacity = settings.config["settings"]["opacity"] reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) @@ -405,4 +406,4 @@ def make_final_video( print_step("Removing temporary files 🗑") cleanups = cleanup(reddit_id) print_substep(f"Removed {cleanups} temporary files 🗑") - print_step("Done! 🎉 The video is in the results folder 📁") \ No newline at end of file + print_step("Done! 🎉 The video is in the results folder 📁") From 07beeafa50f19ba699da53cae5407c6803562777 Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Mon, 22 May 2023 13:16:48 +1000 Subject: [PATCH 13/26] Update screenshot_downloader.py Scrolls comment into view. Without, it can break --- video_creation/screenshot_downloader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index ecff2f4..636a833 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -230,6 +230,8 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): zoom = settings.config["settings"]["zoom"] # zoom the body of the page page.evaluate("document.body.style.zoom="+str(zoom)) + # scroll comment into view + page.locator(f"#t1_{comment['comment_id']}").scroll_into_view_if_needed() # as zooming the body doesn't change the properties of the divs, we need to adjust for the zoom location = page.locator(f"#t1_{comment['comment_id']}").bounding_box() for i in location: From c935d865cae113902692996ab13a9c3bac5272ea Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Wed, 24 May 2023 11:13:42 +1000 Subject: [PATCH 14/26] Create playwright.py util file --- utils/playwright.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 utils/playwright.py diff --git a/utils/playwright.py b/utils/playwright.py new file mode 100644 index 0000000..be046e6 --- /dev/null +++ b/utils/playwright.py @@ -0,0 +1,7 @@ +def clear_cookie_by_name(context, cookie_cleared_name): + cookies = context.cookies() + filtered_cookies = [ + cookie for cookie in cookies if cookie["name"] != cookie_cleared_name + ] + context.clear_cookies() + context.add_cookies(filtered_cookies) From bd015a466a4c69f137551f663196a7c7fd4f6171 Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Wed, 24 May 2023 11:14:48 +1000 Subject: [PATCH 15/26] Update screenshot_downloader.py --- video_creation/screenshot_downloader.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 1c3ab5e..6948644 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -11,6 +11,7 @@ from rich.progress import track from utils import settings from utils.console import print_step, print_substep from utils.imagenarator import imagemaker +from utils.playwright import clear_cookie_by_name from utils.videos import save_data @@ -117,6 +118,13 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): page.wait_for_timeout(5000) page.wait_for_load_state() + # Handle the redesign + # Check if the redesign optout cookie is set + if page.locator("#redesign-beta-optin-btn").is_visible(): + # Clear the redesign optout cookie + clear_cookie_by_name(context, "redesign_optout") + # Reload the page for the redesign to take effect + page.reload() # Get the thread screenshot page.goto(reddit_object["thread_url"], timeout=0) page.set_viewport_size(ViewportSize(width=W, height=H)) From 6aef6666e0f52cae7e82bb8f1c60418002e948cc Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Wed, 24 May 2023 11:27:51 +1000 Subject: [PATCH 16/26] Update elevenlabs.py --- TTS/elevenlabs.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index f427c07..93c6b5c 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -25,10 +25,9 @@ class elevenlabs: if random_voice: voice = self.randomvoice() else: - else: - voice = str( - settings.config["settings"]["tts"]["elevenlabs_voice_name"] - ).capitalize() + voice = str( + settings.config["settings"]["tts"]["elevenlabs_voice_name"] + ).capitalize() if settings.config["settings"]["tts"]["elevenlabs_api_key"]: api_key = settings.config["settings"]["tts"]["elevenlabs_api_key"] From 6d2f20d832f31b923e292cf93340a6d969c5d936 Mon Sep 17 00:00:00 2001 From: liamb Date: Wed, 24 May 2023 12:32:43 +1000 Subject: [PATCH 17/26] fixes evaluate --- video_creation/screenshot_downloader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 1c3ab5e..70f2b08 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -150,7 +150,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): ) page.evaluate( - "tl_content => document.querySelector('[data-test-id=\"post-content\"] > div:nth-child(3) > div > div').textContent = tl_content", + "tl_content => document.querySelector('[data-adclicklocation=\"title\"] > div > div > h1').textContent = tl_content", texts_in_tl, ) else: From 32ea522cd9e57b7d99f6cc044fd180e951a0cccf Mon Sep 17 00:00:00 2001 From: liamb13 <69778531+liamb13@users.noreply.github.com> Date: Sat, 27 May 2023 10:33:09 +1000 Subject: [PATCH 18/26] Update main.py Redact elevenlabs_api_key --- main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/main.py b/main.py index b7a1b7f..1e5101a 100755 --- a/main.py +++ b/main.py @@ -121,6 +121,7 @@ if __name__ == "__main__": shutdown() except Exception as err: config["settings"]["tts"]["tiktok_sessionid"] = "REDACTED" + config["settings"]["tts"]["elevenlabs_api_key"] = "REDACTED" print_step( f"Sorry, something went wrong with this version! Try again, and feel free to report this issue at GitHub or the Discord community.\n" f"Version: {__VERSION__} \n" From 3e6cc23002980944a4cfad4a4511da6f18d42337 Mon Sep 17 00:00:00 2001 From: Simon <65854503+OpenSourceSimon@users.noreply.github.com> Date: Sun, 28 May 2023 12:56:14 +0200 Subject: [PATCH 19/26] Delete codesee-arch-diagram.yml --- .github/workflows/codesee-arch-diagram.yml | 23 ---------------------- 1 file changed, 23 deletions(-) delete mode 100644 .github/workflows/codesee-arch-diagram.yml diff --git a/.github/workflows/codesee-arch-diagram.yml b/.github/workflows/codesee-arch-diagram.yml deleted file mode 100644 index a72f58b..0000000 --- a/.github/workflows/codesee-arch-diagram.yml +++ /dev/null @@ -1,23 +0,0 @@ -# This workflow was added by CodeSee. Learn more at https://codesee.io/ -# This is v2.0 of this workflow file -on: - push: - branches: - - master - pull_request_target: - types: [opened, synchronize, reopened] - -name: CodeSee - -permissions: read-all - -jobs: - codesee: - runs-on: ubuntu-latest - continue-on-error: true - name: Analyze the repo with CodeSee - steps: - - uses: Codesee-io/codesee-action@v2 - with: - codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} - codesee-url: https://app.codesee.io From 19b44b1302bd371c0f204d6c94ac7bc79b892120 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 13:10:29 +0200 Subject: [PATCH 20/26] Add random_voice --- TTS/engine_wrapper.py | 4 +--- utils/.config.template.toml | 1 + video_creation/final_video.py | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TTS/engine_wrapper.py b/TTS/engine_wrapper.py index f040bf7..cdd024e 100644 --- a/TTS/engine_wrapper.py +++ b/TTS/engine_wrapper.py @@ -67,8 +67,6 @@ class TTSEngine: comment["comment_body"] = comment["comment_body"].replace(".. . ", ".") comment["comment_body"] = comment["comment_body"].replace(". . ", ".") comment["comment_body"] = re.sub(r'\."\.', '".', comment["comment_body"]) - print(comment["comment_body"]) - def run(self) -> Tuple[int, int]: Path(self.path).mkdir(parents=True, exist_ok=True) @@ -152,7 +150,7 @@ class TTSEngine: print("OSError") def call_tts(self, filename: str, text: str): - self.tts_module.run(text, filepath=f"{self.path}/{filename}.mp3") + self.tts_module.run(text, filepath=f"{self.path}/{filename}.mp3", random_voice=settings.config["settings"]["tts"]["random_voice"]) # try: # self.length += MP3(f"{self.path}/{filename}.mp3").info.length # except (MutagenError, HeaderNotFoundError): diff --git a/utils/.config.template.toml b/utils/.config.template.toml index a360569..a674f53 100644 --- a/utils/.config.template.toml +++ b/utils/.config.template.toml @@ -44,6 +44,7 @@ background_thumbnail_font_color = { optional = true, default = "255,255,255", ex [settings.tts] voice_choice = { optional = false, default = "streamlabspolly", options = ["streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", ], example = "tiktok", explanation = "The voice platform used for TTS generation. This can be left blank and you will be prompted to choose at runtime." } +random_voice = { optional = false, default = true, example = true, options = [true, false,], explanation = "Randomizes the voice used for each comment" } aws_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for AWS Polly" } streamlabs_polly_voice = { optional = false, default = "Matthew", example = "Matthew", explanation = "The voice used for Streamlabs Polly" } tiktok_voice = { optional = true, default = "en_us_001", example = "en_us_006", explanation = "The voice used for TikTok TTS" } diff --git a/video_creation/final_video.py b/video_creation/final_video.py index ca801c5..0ff652a 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -103,6 +103,7 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str: exit() return output_path + def merge_background_audio(audio: ffmpeg, reddit_id: str): """Gather an audio and merge with assets/backgrounds/background.mp3 Args: From 655c5070105ed87aac204f211fbb77acf4fedb47 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 13:17:22 +0200 Subject: [PATCH 21/26] Couple of fixes including translators fix --- TTS/engine_wrapper.py | 7 ++----- video_creation/final_video.py | 9 ++++----- video_creation/screenshot_downloader.py | 10 +++++----- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/TTS/engine_wrapper.py b/TTS/engine_wrapper.py index e6b92d8..8157032 100644 --- a/TTS/engine_wrapper.py +++ b/TTS/engine_wrapper.py @@ -3,11 +3,8 @@ import re from pathlib import Path from typing import Tuple -# import sox -# from mutagen import MutagenError -# from mutagen.mp3 import MP3, HeaderNotFoundError import numpy as np -import translators as ts +import translators from moviepy.audio.AudioClip import AudioClip from moviepy.audio.fx.volumex import volumex from moviepy.editor import AudioFileClip @@ -172,6 +169,6 @@ def process_text(text: str, clean: bool = True): new_text = sanitize_text(text) if clean else text if lang: print_substep("Translating Text...") - translated_text = ts.google(text, to_language=lang) + translated_text = translators.google(text, to_language=lang) new_text = sanitize_text(translated_text) return new_text diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 4838574..68ff6aa 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -1,13 +1,12 @@ import multiprocessing import os import re -import shutil from os.path import exists # Needs to be imported specifically from typing import Final from typing import Tuple, Any import ffmpeg -import translators as ts +import translators from PIL import Image from rich.console import Console from rich.progress import track @@ -18,12 +17,12 @@ from utils.console import print_step, print_substep from utils.thumbnail import create_thumbnail from utils.videos import save_data -console = Console() - import tempfile import threading import time +console = Console() + class ProgressFfmpeg(threading.Thread): def __init__(self, vid_duration_seconds, progress_update_callback): @@ -73,7 +72,7 @@ def name_normalize(name: str) -> str: lang = settings.config["reddit"]["thread"]["post_lang"] if lang: print_substep("Translating filename...") - translated_name = ts.google(name, to_language=lang) + translated_name = translators.google(name, to_language=lang) return translated_name else: return name diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 636a833..fe9a127 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -3,7 +3,7 @@ import re from pathlib import Path from typing import Dict, Final -import translators as ts +import translators from playwright.async_api import async_playwright # pylint: disable=unused-import from playwright.sync_api import ViewportSize, sync_playwright from rich.progress import track @@ -144,7 +144,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): if lang: print_substep("Translating post...") - texts_in_tl = ts.google( + texts_in_tl = translators.google( reddit_object["thread_title"], to_language=lang, ) @@ -158,7 +158,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): postcontentpath = f"assets/temp/{reddit_id}/png/title.png" try: - if(settings.config["settings"]["zoom"] != 1): + if settings.config["settings"]["zoom"] != 1: # store zoom settings zoom = settings.config["settings"]["zoom"] # zoom the body of the page @@ -216,7 +216,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): # translate code if settings.config["reddit"]["thread"]["post_lang"]: - comment_tl = ts.google( + comment_tl = translators.google( comment["comment_body"], to_language=settings.config["reddit"]["thread"]["post_lang"], ) @@ -225,7 +225,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): [comment_tl, comment["comment_id"]], ) try: - if(settings.config["settings"]["zoom"] != 1): + if settings.config["settings"]["zoom"] != 1: # store zoom settings zoom = settings.config["settings"]["zoom"] # zoom the body of the page From 1dec673841914005018306e65109c477425023e9 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 14:13:16 +0200 Subject: [PATCH 22/26] Update all the requirements, reformat a bit and fix the story mode character limit --- reddit/subreddit.py | 15 +-------------- requirements.txt | 26 +++++++++++++------------- utils/imagenarator.py | 6 +++--- utils/subreddit.py | 15 ++++++++++++++- video_creation/final_video.py | 4 ++-- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/reddit/subreddit.py b/reddit/subreddit.py index 6251610..7bf5a8f 100644 --- a/reddit/subreddit.py +++ b/reddit/subreddit.py @@ -107,20 +107,7 @@ def get_subreddit_threads(POST_ID: str): if submission is None: return get_subreddit_threads(POST_ID) # submission already done. rerun - if settings.config["settings"]["storymode"]: - if not submission.selftext: - print_substep("You are trying to use story mode on post with no post text") - exit() - else: - # Check for the length of the post text - if len(submission.selftext) > ( - settings.config["settings"]["storymode_max_length"] or 2000 - ): - print_substep( - f"Post is too long ({len(submission.selftext)}), try with a different post. ({settings.config['settings']['storymode_max_length']} character limit)" - ) - exit() - elif not submission.num_comments: + elif not submission.num_comments and settings.config["settings"]["storymode"] == "false": print_substep("No comments found. Skipping.") exit() diff --git a/requirements.txt b/requirements.txt index 4459bd1..e06ff0e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,23 +1,23 @@ -boto3==1.24.24 -botocore==1.27.24 -gTTS==2.2.4 +boto3==1.26.142 +botocore==1.29.142 +gTTS==2.3.2 moviepy==1.0.3 -playwright==1.23.0 -praw==7.6.1 +playwright==1.34.0 +praw==7.7.0 prawcore~=2.3.0 -requests==2.28.1 +requests==2.31.0 rich==13.3.5 toml==0.10.2 -translators==5.3.1 +translators==5.7.6 pyttsx3==2.90 -Pillow~=9.4.0 +Pillow==9.5.0 tomlkit==0.11.8 Flask==2.3.2 clean-text==0.6.0 -unidecode==1.3.2 -spacy==3.4.1 -torch==1.12.1 -transformers==4.25.1 +unidecode==1.3.6 +spacy==3.5.3 +torch==2.0.1 +transformers==4.29.2 ffmpeg-python==0.2.0 -elevenlabs==0.2.10 +elevenlabs==0.2.16 yt-dlp==2023.3.4 \ No newline at end of file diff --git a/utils/imagenarator.py b/utils/imagenarator.py index 847073c..aabdb2e 100644 --- a/utils/imagenarator.py +++ b/utils/imagenarator.py @@ -64,13 +64,13 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5, transparent=False) -> id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) if transparent: - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 50) - tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 50) + font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100) + tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100) else: tfont = ImageFont.truetype( os.path.join("fonts", "Roboto-Bold.ttf"), 100 ) # for title - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 90) + font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 100) size = (1920, 1080) image = Image.new("RGBA", size, theme) diff --git a/utils/subreddit.py b/utils/subreddit.py index a883e78..43b5d1d 100644 --- a/utils/subreddit.py +++ b/utils/subreddit.py @@ -57,6 +57,19 @@ def get_subreddit_undone( f'This post has under the specified minimum of comments ({settings.config["reddit"]["thread"]["min_comments"]}). Skipping...' ) continue + if settings.config["settings"]["storymode"]: + if not submission.selftext: + print_substep("You are trying to use story mode on post with no post text") + continue + else: + # Check for the length of the post text + if len(submission.selftext) > ( + settings.config["settings"]["storymode_max_length"] or 2000 + ): + print_substep( + f"Post is too long ({len(submission.selftext)}), try with a different post. ({settings.config['settings']['storymode_max_length']} character limit)" + ) + continue if settings.config["settings"]["storymode"] and not submission.is_self: continue if similarity_scores is not None: @@ -73,7 +86,7 @@ def get_subreddit_undone( ] # set doesn't have __getitem__ index = times_checked + 1 if index == len(VALID_TIME_FILTERS): - print("all time filters have been checked you absolute madlad ") + print("All submissions have been done.") return get_subreddit_undone( subreddit.top( diff --git a/video_creation/final_video.py b/video_creation/final_video.py index c322a4c..0246a37 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -377,9 +377,9 @@ def make_final_video( ) old_percentage = pbar.n pbar.update(100 - old_percentage) - if(allowOnlyTTSFolder): + if allowOnlyTTSFolder: path = defaultPath + f"/OnlyTTS/{filename}" - path = path[:251] + ".mp4" #Prevent a error by limiting the path length, do not change this. + path = path[:251] + ".mp4" # Prevent a error by limiting the path length, do not change this. print_step("Rendering the Only TTS Video 🎥") with ProgressFfmpeg(length, on_update_example) as progress: ffmpeg.output( From 5e19fd757c5279bc709de11de8bfc9ba44e999b4 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 14:15:50 +0200 Subject: [PATCH 23/26] Fix TypeError --- video_creation/final_video.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 0246a37..970d380 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -156,6 +156,9 @@ def make_final_video( # Gather all audio clips audio_clips = list() + if number_of_clips == 0: + print("No audio clips to gather. Please use a different TTS or post.") # This is to fix the TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' + exit() if settings.config["settings"]["storymode"]: if settings.config["settings"]["storymodemethod"] == 0: audio_clips = [ffmpeg.input(f"assets/temp/{reddit_id}/mp3/title.mp3")] From 8e58cd67ecac665754aab105aa911324b769ba06 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 14:28:25 +0200 Subject: [PATCH 24/26] Little fix --- utils/subreddit.py | 2 ++ video_creation/final_video.py | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/subreddit.py b/utils/subreddit.py index 43b5d1d..f9a2f0b 100644 --- a/utils/subreddit.py +++ b/utils/subreddit.py @@ -70,6 +70,8 @@ def get_subreddit_undone( f"Post is too long ({len(submission.selftext)}), try with a different post. ({settings.config['settings']['storymode_max_length']} character limit)" ) continue + elif len(submission.selftext) < 30: + continue if settings.config["settings"]["storymode"] and not submission.is_self: continue if similarity_scores is not None: diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 970d380..f57cd88 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -142,7 +142,7 @@ def make_final_video( # settings values W: Final[int] = int(settings.config["settings"]["resolution_w"]) H: Final[int] = int(settings.config["settings"]["resolution_h"]) - """Fixed to allow fraction opacity Ea: 0.7""" + opacity = settings.config["settings"]["opacity"] reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) @@ -156,7 +156,7 @@ def make_final_video( # Gather all audio clips audio_clips = list() - if number_of_clips == 0: + if number_of_clips == 0 and settings.config["settings"]["storymode"] == "false": print("No audio clips to gather. Please use a different TTS or post.") # This is to fix the TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' exit() if settings.config["settings"]["storymode"]: @@ -347,6 +347,7 @@ def make_final_video( fontcolor="White", fontfile=os.path.join("fonts", "Roboto-Regular.ttf"), ) + background_clip = background_clip.filter("scale", W, H) print_step("Rendering the video 🎥") from tqdm import tqdm From 868fda11f46f42b26812c15b0b5b18007be257ff Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 14:48:32 +0200 Subject: [PATCH 25/26] Edit version number --- main.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index ff76fe4..e3bed2b 100755 --- a/main.py +++ b/main.py @@ -26,7 +26,7 @@ from video_creation.screenshot_downloader import get_screenshots_of_reddit_posts from video_creation.voices import save_text_to_mp3 from utils.ffmpeg_install import ffmpeg_install -__VERSION__ = "3.1" +__VERSION__ = "3.2" print( """ @@ -40,7 +40,7 @@ print( ) # Modified by JasonLovesDoggo print_markdown( - "### Thanks for using this tool! [Feel free to contribute to this project on GitHub!](https://lewismenelaws.com) If you have any questions, feel free to reach out to me on Twitter or submit a GitHub issue. You can find solutions to many common problems in the [Documentation](): https://reddit-video-maker-bot.netlify.app/" + "### Thanks for using this tool! Feel free to contribute to this project on GitHub! If you have any questions, feel free to join my Discord server or submit a GitHub issue. You can find solutions to many common problems in the documentation: https://reddit-video-maker-bot.netlify.app/" ) checkversion(__VERSION__) @@ -90,17 +90,18 @@ def shutdown(): if __name__ == "__main__": if sys.version_info.major != 3 or sys.version_info.minor != 10: - print("Hey! Congratulations, you've made it so far (which is pretty rare with no Python 3.10). Unfortunately, this program only works on Python 3.10. Please install Python 3.10 and try again.") + print( + "Hey! Congratulations, you've made it so far (which is pretty rare with no Python 3.10). Unfortunately, this program only works on Python 3.10. Please install Python 3.10 and try again.") exit() - ffmpeg_install() # install ffmpeg if not installed + ffmpeg_install() # install ffmpeg if not installed directory = Path().absolute() config = settings.check_toml( f"{directory}/utils/.config.template.toml", "config.toml" ) config is False and exit() if ( - not settings.config["settings"]["tts"]["tiktok_sessionid"] - or settings.config["settings"]["tts"]["tiktok_sessionid"] == "" + not settings.config["settings"]["tts"]["tiktok_sessionid"] + or settings.config["settings"]["tts"]["tiktok_sessionid"] == "" ) and config["settings"]["tts"]["voice_choice"] == "tiktok": print_substep( "TikTok voice requires a sessionid! Check our documentation on how to obtain one.", @@ -110,7 +111,7 @@ if __name__ == "__main__": try: if config["reddit"]["thread"]["post_id"]: for index, post_id in enumerate( - config["reddit"]["thread"]["post_id"].split("+") + config["reddit"]["thread"]["post_id"].split("+") ): index += 1 print_step( @@ -139,4 +140,4 @@ if __name__ == "__main__": f"Error: {err} \n" f'Config: {config["settings"]}' ) - raise err \ No newline at end of file + raise err From cab5359e087dff98f524e448ef0da90d9532d039 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 28 May 2023 14:57:28 +0200 Subject: [PATCH 26/26] Reformat --- TTS/elevenlabs.py | 17 +++---- TTS/engine_wrapper.py | 12 +++-- main.py | 9 ++-- reddit/subreddit.py | 5 +- utils/ffmpeg_install.py | 59 +++++++++++++++++----- utils/imagenarator.py | 4 +- utils/subreddit.py | 6 ++- video_creation/background.py | 46 +++++++++-------- video_creation/final_video.py | 65 +++++++++++++++---------- video_creation/screenshot_downloader.py | 28 +++++++---- video_creation/voices.py | 2 +- 11 files changed, 162 insertions(+), 91 deletions(-) diff --git a/TTS/elevenlabs.py b/TTS/elevenlabs.py index 93c6b5c..ab6dbb0 100644 --- a/TTS/elevenlabs.py +++ b/TTS/elevenlabs.py @@ -16,6 +16,7 @@ voices = [ "Sam", ] + class elevenlabs: def __init__(self): self.max_chars = 2500 @@ -33,19 +34,13 @@ class elevenlabs: api_key = settings.config["settings"]["tts"]["elevenlabs_api_key"] else: raise ValueError( - "You didn't set an Elevenlabs API key! Please set the config variable ELEVENLABS_API_KEY to a valid API key." - ) - + "You didn't set an Elevenlabs API key! Please set the config variable ELEVENLABS_API_KEY to a valid API key." + ) + audio = generate( - api_key=api_key, - text=text, - voice=voice, - model="eleven_multilingual_v1" - ) - save( - audio=audio, - filename=filepath + api_key=api_key, text=text, voice=voice, model="eleven_multilingual_v1" ) + save(audio=audio, filename=filepath) def randomvoice(self): return random.choice(self.voices) diff --git a/TTS/engine_wrapper.py b/TTS/engine_wrapper.py index c39649e..b56269e 100644 --- a/TTS/engine_wrapper.py +++ b/TTS/engine_wrapper.py @@ -56,8 +56,10 @@ class TTSEngine: regex_urls = r"((http|https)\:\/\/)?[a-zA-Z0-9\.\/\?\:@\-_=#]+\.([a-zA-Z]){2,6}([a-zA-Z0-9\.\&\/\?\:@\-_=#])*" comment["comment_body"] = re.sub(regex_urls, " ", comment["comment_body"]) comment["comment_body"] = comment["comment_body"].replace("\n", ". ") - comment["comment_body"] = re.sub(r'\bAI\b', 'A.I', comment["comment_body"]) - comment["comment_body"] = re.sub(r'\bAGI\b', 'A.G.I', comment["comment_body"]) + comment["comment_body"] = re.sub(r"\bAI\b", "A.I", comment["comment_body"]) + comment["comment_body"] = re.sub( + r"\bAGI\b", "A.G.I", comment["comment_body"] + ) if comment["comment_body"][-1] != ".": comment["comment_body"] += "." comment["comment_body"] = comment["comment_body"].replace(". . .", ".") @@ -147,7 +149,11 @@ class TTSEngine: print("OSError") def call_tts(self, filename: str, text: str): - self.tts_module.run(text, filepath=f"{self.path}/{filename}.mp3", random_voice=settings.config["settings"]["tts"]["random_voice"]) + self.tts_module.run( + text, + filepath=f"{self.path}/{filename}.mp3", + random_voice=settings.config["settings"]["tts"]["random_voice"], + ) # try: # self.length += MP3(f"{self.path}/{filename}.mp3").info.length # except (MutagenError, HeaderNotFoundError): diff --git a/main.py b/main.py index e3bed2b..23dd55f 100755 --- a/main.py +++ b/main.py @@ -91,7 +91,8 @@ def shutdown(): if __name__ == "__main__": if sys.version_info.major != 3 or sys.version_info.minor != 10: print( - "Hey! Congratulations, you've made it so far (which is pretty rare with no Python 3.10). Unfortunately, this program only works on Python 3.10. Please install Python 3.10 and try again.") + "Hey! Congratulations, you've made it so far (which is pretty rare with no Python 3.10). Unfortunately, this program only works on Python 3.10. Please install Python 3.10 and try again." + ) exit() ffmpeg_install() # install ffmpeg if not installed directory = Path().absolute() @@ -100,8 +101,8 @@ if __name__ == "__main__": ) config is False and exit() if ( - not settings.config["settings"]["tts"]["tiktok_sessionid"] - or settings.config["settings"]["tts"]["tiktok_sessionid"] == "" + not settings.config["settings"]["tts"]["tiktok_sessionid"] + or settings.config["settings"]["tts"]["tiktok_sessionid"] == "" ) and config["settings"]["tts"]["voice_choice"] == "tiktok": print_substep( "TikTok voice requires a sessionid! Check our documentation on how to obtain one.", @@ -111,7 +112,7 @@ if __name__ == "__main__": try: if config["reddit"]["thread"]["post_id"]: for index, post_id in enumerate( - config["reddit"]["thread"]["post_id"].split("+") + config["reddit"]["thread"]["post_id"].split("+") ): index += 1 print_step( diff --git a/reddit/subreddit.py b/reddit/subreddit.py index 7bf5a8f..aea510b 100644 --- a/reddit/subreddit.py +++ b/reddit/subreddit.py @@ -107,7 +107,10 @@ def get_subreddit_threads(POST_ID: str): if submission is None: return get_subreddit_threads(POST_ID) # submission already done. rerun - elif not submission.num_comments and settings.config["settings"]["storymode"] == "false": + elif ( + not submission.num_comments + and settings.config["settings"]["storymode"] == "false" + ): print_substep("No comments found. Skipping.") exit() diff --git a/utils/ffmpeg_install.py b/utils/ffmpeg_install.py index 1f72cfb..acee91a 100644 --- a/utils/ffmpeg_install.py +++ b/utils/ffmpeg_install.py @@ -23,22 +23,36 @@ def ffmpeg_install_windows(): os.remove(f"ffmpeg/doc/{file}") os.rmdir("ffmpeg/doc") # Add to the path - subprocess.run("setx PATH \"%PATH%;%CD%\\ffmpeg\"", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - print("FFmpeg installed successfully! Please restart your computer and then re-run the program.") + subprocess.run( + 'setx PATH "%PATH%;%CD%\\ffmpeg"', + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + print( + "FFmpeg installed successfully! Please restart your computer and then re-run the program." + ) exit() except Exception as e: print( - "An error occurred while trying to install FFmpeg. Please try again. Otherwise, please install FFmpeg manually and try again.") + "An error occurred while trying to install FFmpeg. Please try again. Otherwise, please install FFmpeg manually and try again." + ) print(e) exit() def ffmpeg_install_linux(): try: - subprocess.run("sudo apt install ffmpeg", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + subprocess.run( + "sudo apt install ffmpeg", + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) except Exception as e: print( - "An error occurred while trying to install FFmpeg. Please try again. Otherwise, please install FFmpeg manually and try again.") + "An error occurred while trying to install FFmpeg. Please try again. Otherwise, please install FFmpeg manually and try again." + ) print(e) exit() print("FFmpeg installed successfully! Please re-run the program.") @@ -47,10 +61,16 @@ def ffmpeg_install_linux(): def ffmpeg_install_mac(): try: - subprocess.run("brew install ffmpeg", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + subprocess.run( + "brew install ffmpeg", + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) except FileNotFoundError: print( - "Homebrew is not installed. Please install it and try again. Otherwise, please install FFmpeg manually and try again.") + "Homebrew is not installed. Please install it and try again. Otherwise, please install FFmpeg manually and try again." + ) exit() print("FFmpeg installed successfully! Please re-run the program.") exit() @@ -59,11 +79,20 @@ def ffmpeg_install_mac(): def ffmpeg_install(): try: # Try to run the FFmpeg command - subprocess.run(['ffmpeg', '-version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - print('FFmpeg is installed on this system! If you are seeing this error for the second time, restart your computer.') + subprocess.run( + ["ffmpeg", "-version"], + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + print( + "FFmpeg is installed on this system! If you are seeing this error for the second time, restart your computer." + ) except FileNotFoundError as e: - print('FFmpeg is not installed on this system.') - resp = input("We can try to automatically install it for you. Would you like to do that? (y/n): ") + print("FFmpeg is not installed on this system.") + resp = input( + "We can try to automatically install it for you. Would you like to do that? (y/n): " + ) if resp.lower() == "y": print("Installing FFmpeg...") if os.name == "nt": @@ -73,12 +102,16 @@ def ffmpeg_install(): elif os.name == "mac": ffmpeg_install_mac() else: - print("Your OS is not supported. Please install FFmpeg manually and try again.") + print( + "Your OS is not supported. Please install FFmpeg manually and try again." + ) exit() else: print("Please install FFmpeg manually and try again.") exit() except Exception as e: - print("Welcome fellow traveler! You're one of the few who have made it this far. We have no idea how you got at this error, but we're glad you're here. Please report this error to the developer, and we'll try to fix it as soon as possible. Thank you for your patience!") + print( + "Welcome fellow traveler! You're one of the few who have made it this far. We have no idea how you got at this error, but we're glad you're here. Please report this error to the developer, and we'll try to fix it as soon as possible. Thank you for your patience!" + ) print(e) return None diff --git a/utils/imagenarator.py b/utils/imagenarator.py index aabdb2e..9427a42 100644 --- a/utils/imagenarator.py +++ b/utils/imagenarator.py @@ -57,9 +57,7 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5, transparent=False) -> """ Render Images for video """ - title = process_text( - reddit_obj["thread_title"], False - ) + title = process_text(reddit_obj["thread_title"], False) texts = reddit_obj["thread_post"] id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) diff --git a/utils/subreddit.py b/utils/subreddit.py index f9a2f0b..ac4a604 100644 --- a/utils/subreddit.py +++ b/utils/subreddit.py @@ -59,12 +59,14 @@ def get_subreddit_undone( continue if settings.config["settings"]["storymode"]: if not submission.selftext: - print_substep("You are trying to use story mode on post with no post text") + print_substep( + "You are trying to use story mode on post with no post text" + ) continue else: # Check for the length of the post text if len(submission.selftext) > ( - settings.config["settings"]["storymode_max_length"] or 2000 + settings.config["settings"]["storymode_max_length"] or 2000 ): print_substep( f"Post is too long ({len(submission.selftext)}), try with a different post. ({settings.config['settings']['storymode_max_length']} character limit)" diff --git a/video_creation/background.py b/video_creation/background.py index 7cfdf81..1fb1ffc 100644 --- a/video_creation/background.py +++ b/video_creation/background.py @@ -3,14 +3,15 @@ import random import re from pathlib import Path from random import randrange -from typing import Any, Tuple,Dict +from typing import Any, Tuple, Dict -from moviepy.editor import VideoFileClip,AudioFileClip +from moviepy.editor import VideoFileClip, AudioFileClip from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip from utils import settings from utils.console import print_step, print_substep import yt_dlp + def load_background_options(): background_options = {} # Load background videos @@ -20,11 +21,11 @@ def load_background_options(): # Load background audios with open("./utils/background_audios.json") as json_file: background_options["audio"] = json.load(json_file) - + # Remove "__comment" from backgrounds del background_options["video"]["__comment"] del background_options["audio"]["__comment"] - + # Add position lambda function # (https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html#moviepy.video.VideoClip.VideoClip.set_position) for name in list(background_options["video"].keys()): @@ -36,7 +37,6 @@ def load_background_options(): return background_options - def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]: """Generates a random interval of time to be used as the background of the video. @@ -49,11 +49,11 @@ def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int """ initialValue = 180 # Issue #1649 - Ensures that will be a valid interval in the video - while(int(length_of_clip) <= int(video_length+initialValue)): - if(initialValue == initialValue //2): + while int(length_of_clip) <= int(video_length + initialValue): + if initialValue == initialValue // 2: raise Exception("Your background is too short for this video length") else: - initialValue //= 2 #Divides the initial value by 2 until reach 0 + initialValue //= 2 # Divides the initial value by 2 until reach 0 random_time = randrange(initialValue, int(length_of_clip) - int(video_length)) return random_time, random_time + video_length @@ -75,6 +75,7 @@ def get_background_config(mode: str): return background_options[mode][choice] + def download_background_video(background_config: Tuple[str, str, str, Any]): """Downloads the background/s video from YouTube.""" Path("./assets/backgrounds/video/").mkdir(parents=True, exist_ok=True) @@ -88,7 +89,7 @@ def download_background_video(background_config: Tuple[str, str, str, Any]): print_substep("Downloading the backgrounds videos... please be patient 🙏 ") print_substep(f"Downloading {filename} from {uri}") ydl_opts = { - 'format': "bestvideo[height<=1080][ext=mp4]", + "format": "bestvideo[height<=1080][ext=mp4]", "outtmpl": f"assets/backgrounds/video/{credit}-{filename}", "retries": 10, } @@ -97,6 +98,7 @@ def download_background_video(background_config: Tuple[str, str, str, Any]): ydl.download(uri) print_substep("Background video downloaded successfully! 🎉", style="bold green") + def download_background_audio(background_config: Tuple[str, str, str]): """Downloads the background/s audio from YouTube.""" Path("./assets/backgrounds/audio/").mkdir(parents=True, exist_ok=True) @@ -110,9 +112,9 @@ def download_background_audio(background_config: Tuple[str, str, str]): print_substep("Downloading the backgrounds audio... please be patient 🙏 ") print_substep(f"Downloading {filename} from {uri}") ydl_opts = { - 'outtmpl': f'./assets/backgrounds/audio/{credit}-{filename}', - 'format': 'bestaudio/best', - 'extract_audio': True, + "outtmpl": f"./assets/backgrounds/audio/{credit}-{filename}", + "format": "bestaudio/best", + "extract_audio": True, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: @@ -121,9 +123,8 @@ def download_background_audio(background_config: Tuple[str, str, str]): print_substep("Background audio downloaded successfully! 🎉", style="bold green") - def chop_background( - background_config: Dict[str,Tuple], video_length: int, reddit_object: dict + background_config: Dict[str, Tuple], video_length: int, reddit_object: dict ): """Generates the background audio and footage to be used in the video and writes it to assets/temp/background.mp3 and assets/temp/background.mp4 @@ -133,20 +134,26 @@ def chop_background( """ id = re.sub(r"[^\w\s-]", "", reddit_object["thread_id"]) - if(settings.config["settings"]["background"][f"background_audio_volume"] == 0): + if settings.config["settings"]["background"][f"background_audio_volume"] == 0: print_step("Volume was set to 0. Skipping background audio creation . . .") else: print_step("Finding a spot in the backgrounds audio to chop...✂️") - audio_choice = f"{background_config['audio'][2]}-{background_config['audio'][1]}" + audio_choice = ( + f"{background_config['audio'][2]}-{background_config['audio'][1]}" + ) background_audio = AudioFileClip(f"assets/backgrounds/audio/{audio_choice}") - start_time_audio, end_time_audio = get_start_and_end_times(video_length, background_audio.duration) - background_audio = background_audio.subclip(start_time_audio,end_time_audio) + start_time_audio, end_time_audio = get_start_and_end_times( + video_length, background_audio.duration + ) + background_audio = background_audio.subclip(start_time_audio, end_time_audio) background_audio.write_audiofile(f"assets/temp/{id}/background.mp3") print_step("Finding a spot in the backgrounds video to chop...✂️") video_choice = f"{background_config['video'][2]}-{background_config['video'][1]}" background_video = VideoFileClip(f"assets/backgrounds/video/{video_choice}") - start_time_video, end_time_video = get_start_and_end_times(video_length, background_video.duration) + start_time_video, end_time_video = get_start_and_end_times( + video_length, background_video.duration + ) # Extract video subclip try: ffmpeg_extract_subclip( @@ -163,5 +170,6 @@ def chop_background( print_substep("Background video chopped successfully!", style="bold green") return background_config["video"][2] + # Create a tuple for downloads background (background_audio_options, background_video_options) background_options = load_background_options() diff --git a/video_creation/final_video.py b/video_creation/final_video.py index f57cd88..34eb449 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -1,7 +1,7 @@ import multiprocessing import os import re -from os.path import exists # Needs to be imported specifically +from os.path import exists # Needs to be imported specifically from typing import Final from typing import Tuple, Any, Dict @@ -109,28 +109,27 @@ def merge_background_audio(audio: ffmpeg, reddit_id: str): audio (ffmpeg): The TTS final audio but without background. reddit_id (str): The ID of subreddit """ - background_audio_volume = settings.config["settings"]["background"]["background_audio_volume"] - if (background_audio_volume == 0): - return audio # Return the original audio + background_audio_volume = settings.config["settings"]["background"][ + "background_audio_volume" + ] + if background_audio_volume == 0: + return audio # Return the original audio else: # sets volume to config - bg_audio = ( - ffmpeg.input(f"assets/temp/{reddit_id}/background.mp3") - .filter( - "volume", - background_audio_volume, - ) + bg_audio = ffmpeg.input(f"assets/temp/{reddit_id}/background.mp3").filter( + "volume", + background_audio_volume, ) # Merges audio and background_audio merged_audio = ffmpeg.filter([audio, bg_audio], "amix", duration="longest") - return merged_audio # Return merged audio + return merged_audio # Return merged audio def make_final_video( number_of_clips: int, length: int, reddit_obj: dict, - background_config: Dict[str,Tuple], + background_config: Dict[str, Tuple], ): """Gathers audio clips, gathers all screenshots, stitches them together and saves the final video to assets/temp Args: @@ -147,8 +146,10 @@ def make_final_video( reddit_id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) - allowOnlyTTSFolder: bool = settings.config["settings"]["background"]["enable_extra_audio"] \ - and settings.config["settings"]["background"]["background_audio_volume"] != 0 + allowOnlyTTSFolder: bool = ( + settings.config["settings"]["background"]["enable_extra_audio"] + and settings.config["settings"]["background"]["background_audio_volume"] != 0 + ) print_step("Creating the final video 🎥") @@ -157,7 +158,9 @@ def make_final_video( # Gather all audio clips audio_clips = list() if number_of_clips == 0 and settings.config["settings"]["storymode"] == "false": - print("No audio clips to gather. Please use a different TTS or post.") # This is to fix the TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' + print( + "No audio clips to gather. Please use a different TTS or post." + ) # This is to fix the TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' exit() if settings.config["settings"]["storymode"]: if settings.config["settings"]["storymodemethod"] == 0: @@ -208,7 +211,7 @@ def make_final_video( screenshot_width = int((W * 45) // 100) audio = ffmpeg.input(f"assets/temp/{reddit_id}/audio.mp3") - final_audio = merge_background_audio(audio,reddit_id) + final_audio = merge_background_audio(audio, reddit_id) image_clips = list() @@ -291,11 +294,15 @@ def make_final_video( subreddit = settings.config["reddit"]["thread"]["subreddit"] if not exists(f"./results/{subreddit}"): - print_substep("The 'results' folder could not be found so it was automatically created.") + print_substep( + "The 'results' folder could not be found so it was automatically created." + ) os.makedirs(f"./results/{subreddit}") - + if not exists(f"./results/{subreddit}/OnlyTTS") and allowOnlyTTSFolder: - print_substep("The 'OnlyTTS' folder could not be found so it was automatically created.") + print_substep( + "The 'OnlyTTS' folder could not be found so it was automatically created." + ) os.makedirs(f"./results/{subreddit}/OnlyTTS") # create a thumbnail for the video @@ -303,7 +310,9 @@ def make_final_video( if settingsbackground["background_thumbnail"]: if not exists(f"./results/{subreddit}/thumbnails"): - print_substep("The 'results/thumbnails' folder could not be found so it was automatically created.") + print_substep( + "The 'results/thumbnails' folder could not be found so it was automatically created." + ) os.makedirs(f"./results/{subreddit}/thumbnails") # get the first file with the .png extension from assets/backgrounds and use it as a background for the thumbnail first_image = next( @@ -361,11 +370,13 @@ def make_final_video( defaultPath = f"results/{subreddit}" with ProgressFfmpeg(length, on_update_example) as progress: path = defaultPath + f"/{filename}" - path = path[:251] + ".mp4" #Prevent a error by limiting the path length, do not change this. + path = ( + path[:251] + ".mp4" + ) # Prevent a error by limiting the path length, do not change this. ffmpeg.output( background_clip, final_audio, - path, + path, f="mp4", **{ "c:v": "h264", @@ -383,7 +394,9 @@ def make_final_video( pbar.update(100 - old_percentage) if allowOnlyTTSFolder: path = defaultPath + f"/OnlyTTS/{filename}" - path = path[:251] + ".mp4" # Prevent a error by limiting the path length, do not change this. + path = ( + path[:251] + ".mp4" + ) # Prevent a error by limiting the path length, do not change this. print_step("Rendering the Only TTS Video 🎥") with ProgressFfmpeg(length, on_update_example) as progress: ffmpeg.output( @@ -397,7 +410,9 @@ def make_final_video( "b:a": "192k", "threads": multiprocessing.cpu_count(), }, - ).overwrite_output().global_args("-progress", progress.output_file.name).run( + ).overwrite_output().global_args( + "-progress", progress.output_file.name + ).run( quiet=True, overwrite_output=True, capture_stdout=False, @@ -406,7 +421,7 @@ def make_final_video( old_percentage = pbar.n pbar.update(100 - old_percentage) pbar.close() - save_data(subreddit, filename + ".mp4", title, idx, background_config['video'][2]) + save_data(subreddit, filename + ".mp4", title, idx, background_config["video"][2]) print_step("Removing temporary files 🗑") cleanups = cleanup(reddit_id) print_substep(f"Removed {cleanups} temporary files 🗑") diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 26ce9a3..eea5801 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -116,7 +116,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): ) page.locator("button[class$='m-full-width']").click() page.wait_for_timeout(5000) - + login_error_div = page.locator(".AnimatedForm__errorMessage").first if login_error_div.is_visible(): login_error_message = login_error_div.inner_text() @@ -125,7 +125,10 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): pass else: # The div contains an error message - print_substep("Your reddit credentials are incorrect! Please modify them accordingly in the config.toml file.", style="red") + print_substep( + "Your reddit credentials are incorrect! Please modify them accordingly in the config.toml file.", + style="red", + ) exit() else: pass @@ -183,11 +186,11 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): # store zoom settings zoom = settings.config["settings"]["zoom"] # zoom the body of the page - page.evaluate("document.body.style.zoom="+str(zoom)) + page.evaluate("document.body.style.zoom=" + str(zoom)) # as zooming the body doesn't change the properties of the divs, we need to adjust for the zoom location = page.locator('[data-test-id="post-content"]').bounding_box() for i in location: - location[i] = float("{:.2f}".format(location[i]*zoom)) + location[i] = float("{:.2f}".format(location[i] * zoom)) page.screenshot(clip=location, path=postcontentpath) else: page.locator('[data-test-id="post-content"]').screenshot( @@ -250,14 +253,21 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): # store zoom settings zoom = settings.config["settings"]["zoom"] # zoom the body of the page - page.evaluate("document.body.style.zoom="+str(zoom)) + page.evaluate("document.body.style.zoom=" + str(zoom)) # scroll comment into view - page.locator(f"#t1_{comment['comment_id']}").scroll_into_view_if_needed() + page.locator( + f"#t1_{comment['comment_id']}" + ).scroll_into_view_if_needed() # as zooming the body doesn't change the properties of the divs, we need to adjust for the zoom - location = page.locator(f"#t1_{comment['comment_id']}").bounding_box() + location = page.locator( + f"#t1_{comment['comment_id']}" + ).bounding_box() for i in location: - location[i] = float("{:.2f}".format(location[i]*zoom)) - page.screenshot(clip=location, path=f"assets/temp/{reddit_id}/png/comment_{idx}.png") + location[i] = float("{:.2f}".format(location[i] * zoom)) + page.screenshot( + clip=location, + path=f"assets/temp/{reddit_id}/png/comment_{idx}.png", + ) else: page.locator(f"#t1_{comment['comment_id']}").screenshot( path=f"assets/temp/{reddit_id}/png/comment_{idx}.png" diff --git a/video_creation/voices.py b/video_creation/voices.py index cd75f06..0dcc87d 100644 --- a/video_creation/voices.py +++ b/video_creation/voices.py @@ -20,7 +20,7 @@ TTSProviders = { "StreamlabsPolly": StreamlabsPolly, "TikTok": TikTok, "pyttsx": pyttsx, - "ElevenLabs": elevenlabs + "ElevenLabs": elevenlabs, }