diff --git a/TTS/engine_wrapper.py b/TTS/engine_wrapper.py index 8751880..3daa2e1 100644 --- a/TTS/engine_wrapper.py +++ b/TTS/engine_wrapper.py @@ -72,8 +72,6 @@ class TTSEngine: comment["comment_body"] = re.sub(r'\."\.', '".', comment["comment_body"]) def run(self) -> Tuple[int, int]: - from utils.imagenarator import comment_image_maker - Path(self.path).mkdir(parents=True, exist_ok=True) print_step("Saving Text to MP3 files...") @@ -94,7 +92,6 @@ class TTSEngine: else: comments = [] - os.makedirs("assets/temp/" + self.redditid + "/png", exist_ok=True) for idx, comment in track(enumerate(self.reddit_object["comments"]), "Saving..."): # TODO: Maybe move this somewhere better? comments.append(comment["comment_body"]) @@ -111,10 +108,6 @@ class TTSEngine: else: # If the comment is not too long, just call the tts engine self.call_tts(f"{idx}", process_text(comment["comment_body"])) - # TODO: Maybe move this somewhere better? - if not settings.config["settings"]["use_capcut"]: - comment_image_maker((0, 0, 0, 0), self.reddit_object, comments, (255, 255, 255), transparent=True) - print_substep("Saved Text to MP3 files successfully.", style="bold green") return self.length, idx diff --git a/main.py b/main.py index ab32f54..6d145f4 100755 --- a/main.py +++ b/main.py @@ -28,7 +28,7 @@ from video_creation.screenshot_downloader import get_screenshots_of_reddit_posts from video_creation.voices import save_text_to_mp3 from video_creation.memes import make_meme_video -__VERSION__ = "3.2.1" +__VERSION__ = "3.2.2" print( """ @@ -114,7 +114,7 @@ if __name__ == "__main__": print_markdown("## Invalid credentials") print_markdown("Please check your credentials in the config.toml file") shutdown() - except Exception as err: + except Exception as err: 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" diff --git a/utils/.config.template.toml b/utils/.config.template.toml index 853a5ff..59e0028 100644 --- a/utils/.config.template.toml +++ b/utils/.config.template.toml @@ -203,7 +203,6 @@ resolution_w = { optional = false, default = 1080, example = 1440, explantation 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" } channel_name = { optional = true, default = "Reddit Tales", example = "Reddit Stories", explanation = "Sets the username that appaers in the fancy title screen" } -words_on_screen = { optional = true, default = 10, example = 1, type = "int", explanation = "Sets how many words should be shown on screen" } [settings.background] background_video = { optional = true, default = "minecraft", example = "rocket-league", options = [ diff --git a/utils/capcut.py b/utils/capcut.py index cf00d5b..d6dc085 100644 --- a/utils/capcut.py +++ b/utils/capcut.py @@ -36,6 +36,7 @@ def generate_captions(file_path, title): page.click("//span[contains(text(),'OK')]") + print("Logging in") page.goto("https://www.capcut.com/login") page.fill("//input[@class='lv-input lv-input-size-default lv_sign_in_panel_wide-input']", email) @@ -65,6 +66,7 @@ def generate_captions(file_path, title): if page.is_visible("//div[@class='guide-modal-close-icon']"): page.click("//div[@class='guide-modal-close-icon']") + print("Trying to remove old video") if page.is_visible("//div[@data-selectable-item-id]"): page.hover("//div[@data-selectable-item-id]") @@ -85,6 +87,7 @@ def generate_captions(file_path, title): page.goto("https://www.capcut.com/editor?enter_from=create_new¤t_page=landing_page&from_page=work_space&start_tab=video&__action_from=my_draft&position=my_draft&scenario=youtube_ads&scale=9%3A16") + print("Uploading video") if page.is_visible("//div[@class='guide-close-icon-f8J9FZ']//*[name()='svg']"): page.click("//div[@class='guide-close-icon-f8J9FZ']//*[name()='svg']") @@ -106,11 +109,18 @@ def generate_captions(file_path, title): if page.is_visible("//div[@class='guide-close-icon-OwPlMC']"): page.click("//div[@class='guide-close-icon-OwPlMC']") + while True: + try: + page.click("div[class^='guide-close-icon-']", timeout=1000) + except: + break + + page.set_input_files("(//input[@type='file'])[1]", file_path) time.sleep(2) - page.click("//div[@class='tools-dCzTyg']") + page.click("//div[@class='tools-97tWCU']") page.click("(//li[@role='option'])[5]") time.sleep(18) @@ -143,7 +153,7 @@ def generate_captions(file_path, title): time.sleep(1) - page.click(f"(//img[@class='image-QII91y'])[{str(settings.config['capcut']['preset_number'])}]") + page.click(f"(//img[@class='image-E7GTkW'])[{str(settings.config['capcut']['preset_number'])}]") time.sleep(2) diff --git a/utils/imagenarator.py b/utils/imagenarator.py index ac6b149..b80d385 100644 --- a/utils/imagenarator.py +++ b/utils/imagenarator.py @@ -7,7 +7,6 @@ from rich.progress import track from TTS.engine_wrapper import process_text from utils.console import print_step, print_substep -from utils.process_post import split_text def draw_multiple_line_text( @@ -64,7 +63,7 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5, transparent=False) -> texts = reddit_obj["thread_post"] id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) - texts = split_text(" ".join(texts)) + #texts = split_text(" ".join(texts)) if transparent: font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100) @@ -77,29 +76,3 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5, transparent=False) -> text = process_text(text, False) draw_multiple_line_text(image, text, font, txtclr, padding, wrap=30, transparent=transparent) image.save(f"assets/temp/{id}/png/img{idx}.png") - -def comment_image_maker(theme, reddit_obj: dict, comments, txtclr, padding=5, transparent=False) -> None: - """ - Render Images for video - """ - id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) - - if transparent: - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100) - else: - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 100) - size = (1920, 1080) - - print_step("Rendering Images") - - i = 0 - for comment in comments: - texts = split_text(comment) - for text in texts: - image = Image.new("RGBA", size, theme) - text = process_text(text, False) - draw_multiple_line_text(image, text, font, txtclr, padding, wrap=30, transparent=transparent) - print_substep("Made image: " + str(i)) - image.save(f"assets/temp/{id}/png/comment_{i}.png") - - i+=1 \ No newline at end of file diff --git a/utils/process_post.py b/utils/process_post.py deleted file mode 100644 index 642a71c..0000000 --- a/utils/process_post.py +++ /dev/null @@ -1,16 +0,0 @@ -import re -from typing import List - -from utils import settings - - -# working good -def split_text(obj) -> List[str]: - text: str = re.sub("\n", " ", obj) - - words_on_screen = settings.config["settings"]["words_on_screen"] - - words = text.split() - grouped_words = [' '.join(words[i: i + words_on_screen]) for i in range(0, len(words), words_on_screen)] - - return grouped_words diff --git a/utils/thumbnail.py b/utils/thumbnail.py index 172b454..6a0b215 100644 --- a/utils/thumbnail.py +++ b/utils/thumbnail.py @@ -1,4 +1,9 @@ -from PIL import ImageDraw, ImageFont +import textwrap +import os + +from PIL import ImageDraw, ImageFont, Image +from utils import settings +from utils.console import print_step, print_substep def create_thumbnail(thumbnail, font_family, font_size, font_color, width, height, title): @@ -33,3 +38,38 @@ def create_thumbnail(thumbnail, font_family, font_size, font_color, width, heigh draw.text((MarginXaxis, MarginYaxis + (LineHeight * i)), arrayTitle[i], rgb, font=font) return thumbnail + +def create_fancy_thumbnail(image, text, text_color, padding, wrap=35): + print_step(f"Creating fancy thumbnail for: {text}") + font_title_size = 47 + font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) + image_width, image_height = image.size + lines = textwrap.wrap(text, width=wrap) + y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 30 + draw = ImageDraw.Draw(image) + + username_font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 30) + draw.text((205, 825), settings.config["settings"]["channel_name"], font=username_font, fill=text_color, align="left") + + if len(lines) == 3: + lines = textwrap.wrap(text, width=wrap+10) + font_title_size = 40 + font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) + y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 35 + elif len(lines) == 4: + lines = textwrap.wrap(text, width=wrap+10) + font_title_size = 35 + font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) + y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 40 + elif len(lines) > 4: + lines = textwrap.wrap(text, width=wrap+10) + font_title_size = 30 + font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) + y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 30 + + for line in lines: + _, line_height = font.getsize(line) + draw.text((120, y), line, font=font, fill=text_color, align="left") + y += line_height + padding + + return image diff --git a/video_creation/final_video.py b/video_creation/final_video.py index 4e005be..9461602 100644 --- a/video_creation/final_video.py +++ b/video_creation/final_video.py @@ -17,11 +17,11 @@ from rich.progress import track from utils import settings from utils import capcut +from utils import thumbnail from utils.cleanup import cleanup from utils.console import print_step, print_substep -from utils.thumbnail import create_thumbnail +from utils.thumbnail import create_thumbnail, create_fancy_thumbnail from utils.videos import save_data -from utils.process_post import split_text from pathlib import Path @@ -111,43 +111,6 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str: exit(1) return output_path - -# The following function is based on code under: Copyright 2024 beingbored (aka. Tim), MIT License, permission granted to use, copy, modify, and distribute. -def create_fancy_thumbnail(image, text, text_color, padding, wrap=35): - print_step(f"Creating fancy thumbnail for: {text}") - font_title_size = 47 - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) - image_width, image_height = image.size - lines = textwrap.wrap(text, width=wrap) - y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 30 - draw = ImageDraw.Draw(image) - - username_font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 30) - draw.text((205, 825), settings.config["settings"]["channel_name"], font=username_font, fill=text_color, align="left") - - if len(lines) == 3: - lines = textwrap.wrap(text, width=wrap+10) - font_title_size = 40 - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) - y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 35 - elif len(lines) == 4: - lines = textwrap.wrap(text, width=wrap+10) - font_title_size = 35 - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) - y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 40 - elif len(lines) > 4: - lines = textwrap.wrap(text, width=wrap+10) - font_title_size = 30 - font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), font_title_size) - y = (image_height / 2) - (((font.getsize(text)[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2) + 30 - - for line in lines: - _, line_height = font.getsize(line) - draw.text((120, y), line, font=font, fill=text_color, align="left") - y += line_height + padding - - return image - def merge_background_audio(audio: ffmpeg, reddit_id: str): """Gather an audio and merge with assets/backgrounds/background.mp3 Args: @@ -246,8 +209,6 @@ def make_final_video( if not settings.config["settings"]["mememode"]: Path(f"assets/temp/{reddit_id}/png").mkdir(parents=True, exist_ok=True) - # Copyright 2024 beingbored (aka. Tim), MIT License, permission granted to use, copy, modify, and distribute. - # get the title_template image and draw a text in the middle part of it with the title of the thread title_template = Image.open("assets/title_template.png") title = reddit_obj["thread_title"] @@ -265,8 +226,6 @@ def make_final_video( title_img.save(f"assets/temp/{reddit_id}/png/title.png") - # Copyright end - image_clips.insert( 0, ffmpeg.input(f"assets/temp/{reddit_id}/png/title.png")["v"].filter( @@ -307,27 +266,19 @@ def make_final_video( ffmpeg.probe(f"assets/temp/{reddit_id}/mp3/title.mp3")["format"]["duration"] ) - text = " ".join(reddit_obj["thread_post"]) - number_of_clips_splitted = len(split_text(text)) - - # TODO: Fix that it sometimes goes out of sync - for i in track(range(0, number_of_clips_splitted + 1), "Collecting the image files..."): - time_for_clip = total_audio_duration/(number_of_clips_splitted+1) - if i == 0: - time_for_clip = float(ffmpeg.probe(f"assets/temp/{reddit_id}/mp3/title.mp3")["format"]["duration"]) - image_clips.append( - ffmpeg.input(f"assets/temp/{reddit_id}/png/img{i}.png")["v"].filter( - "scale", screenshot_width, -1 - ) + time_for_clip = float(ffmpeg.probe(f"assets/temp/{reddit_id}/mp3/title.mp3")["format"]["duration"]) + image_clips.append( + ffmpeg.input(f"assets/temp/{reddit_id}/png/img{0}.png")["v"].filter( + "scale", screenshot_width, -1 ) + ) - background_clip = background_clip.overlay( - image_clips[i], - enable=f"between(t,{current_time},{current_time + time_for_clip})", - x="(main_w-overlay_w)/2", - y="(main_h-overlay_h)/2", - ) - current_time += time_for_clip + background_clip = background_clip.overlay( + image_clips[0], + enable=f"between(t,{current_time},{current_time + time_for_clip})", + x="(main_w-overlay_w)/2", + y="(main_h-overlay_h)/2", + ) else: total_audio_duration = float( ffmpeg.probe(f"assets/temp/{reddit_id}/audio.mp3")["format"]["duration"] @@ -343,13 +294,6 @@ def make_final_video( ) for i in range(0, num_files): - time_for_clip = total_audio_duration/(num_files) - image_clips.append( - ffmpeg.input(f"assets/temp/{reddit_id}/png/comment_{i}.png")["v"].filter( - "scale", screenshot_width, -1 - ) - ) - if i == 0: time_for_clip = float(ffmpeg.probe(f"assets/temp/{reddit_id}/mp3/title.mp3")["format"]["duration"]) diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 6684fd8..5bc986b 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -11,7 +11,6 @@ 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 @@ -61,15 +60,6 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int): bgcolor = (255, 255, 255, 255) txtcolor = (0, 0, 0) transparent = False - if storymode and settings.config["settings"]["storymodemethod"] == 1: - # for idx,item in enumerate(reddit_object["thread_post"]): - print_substep("Generating images...") - return imagemaker( - theme=bgcolor, - reddit_obj=reddit_object, - txtclr=txtcolor, - transparent=transparent, - ) if settings.config["settings"]["storymodemethod"] == 1: return