Merge pull request #2051 from Cyteon/fancy-title-screen

Adds Fancy title screen
pull/2057/head
Cyteon 1 year ago committed by GitHub
commit 5fa7b112be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

3
.gitignore vendored

@ -231,7 +231,8 @@ fabric.properties
# Android studio 3.1+ serialized cache file # Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
assets/ assets/temp
assets/backgrounds
/.vscode /.vscode
out out
.DS_Store .DS_Store

@ -81,7 +81,7 @@ I have tried to simplify the code so anyone can read it and start contributing a
Please read our [contributing guidelines](CONTRIBUTING.md) for more detailed information. Please read our [contributing guidelines](CONTRIBUTING.md) for more detailed information.
### For any questions or support join the [Discord](https://discord.gg/Vkanmh6C8V) server ### For any questions or support join the [Discord](https://discord.gg/qfQSx45xCV) server
## Developers and maintainers. ## Developers and maintainers.
@ -101,6 +101,8 @@ Freebiell (Freebie#3263) - https://github.com/FreebieII
Aman Raza (electro199#8130) - https://github.com/electro199 Aman Raza (electro199#8130) - https://github.com/electro199
Cyteon (cyteon) - https://github.com/cyteon
## LICENSE ## LICENSE
[Roboto Fonts](https://fonts.google.com/specimen/Roboto/about) are licensed under [Apache License V2](https://www.apache.org/licenses/LICENSE-2.0) [Roboto Fonts](https://fonts.google.com/specimen/Roboto/about) are licensed under [Apache License V2](https://www.apache.org/licenses/LICENSE-2.0)

@ -43,9 +43,11 @@ class StreamlabsPolly:
f"Please set the config variable STREAMLABS_POLLY_VOICE to a valid voice. options are: {voices}" f"Please set the config variable STREAMLABS_POLLY_VOICE to a valid voice. options are: {voices}"
) )
voice = str(settings.config["settings"]["tts"]["streamlabs_polly_voice"]).capitalize() voice = str(settings.config["settings"]["tts"]["streamlabs_polly_voice"]).capitalize()
body = {"voice": voice, "text": text, "service": "polly"} body = {"voice": voice, "text": text, "service": "polly"}
headers = {"Referer": "https://streamlabs.com/"} headers = {"Referer": "https://streamlabs.com/"}
response = requests.post(self.url, headers=headers, data=body) response = requests.post(self.url, headers=headers, data=body)
if not check_ratelimit(response): if not check_ratelimit(response):
self.run(text, filepath, random_voice) self.run(text, filepath, random_voice)

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@ -81,7 +81,7 @@ def shutdown() -> NoReturn:
if __name__ == "__main__": if __name__ == "__main__":
if sys.version_info.major != 3 or sys.version_info.minor != 10: if sys.version_info.major != 3 or sys.version_info.minor not in [10, 11]:
print( 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."
) )

@ -104,7 +104,7 @@ def get_subreddit_threads(POST_ID: str):
upvotes = submission.score upvotes = submission.score
ratio = submission.upvote_ratio * 100 ratio = submission.upvote_ratio * 100
num_comments = submission.num_comments num_comments = submission.num_comments
threadurl = f"https://reddit.com{submission.permalink}" threadurl = f"https://new.reddit.com/{submission.permalink}"
print_substep(f"Video will be: {submission.title} :thumbsup:", style="bold green") print_substep(f"Video will be: {submission.title} :thumbsup:", style="bold green")
print_substep(f"Thread url is: {threadurl} :thumbsup:", style="bold green") print_substep(f"Thread url is: {threadurl} :thumbsup:", style="bold green")

@ -31,6 +31,7 @@ storymode_max_length = { optional = true, default = 1000, example = 1000, explan
resolution_w = { optional = false, default = 1080, example = 1440, explantation = "Sets the width in pixels of the final video" } 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" } 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" } 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 channel name for the video" }
[settings.background] [settings.background]
background_video = { 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" } background_video = { 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" }

@ -56,25 +56,17 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5, transparent=False) ->
""" """
Render Images for video Render Images for video
""" """
title = process_text(reddit_obj["thread_title"], False)
texts = reddit_obj["thread_post"] texts = reddit_obj["thread_post"]
id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"]) id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"])
if transparent: if transparent:
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100) font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100)
tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100)
else: else:
tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 100) # for title
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 100) font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 100)
size = (1920, 1080) size = (1920, 1080)
image = Image.new("RGBA", size, theme) image = Image.new("RGBA", size, theme)
# for title
draw_multiple_line_text(image, title, tfont, txtclr, padding, wrap=30, transparent=transparent)
image.save(f"assets/temp/{id}/png/title.png")
for idx, text in track(enumerate(texts), "Rendering Image"): for idx, text in track(enumerate(texts), "Rendering Image"):
image = Image.new("RGBA", size, theme) image = Image.new("RGBA", size, theme)
text = process_text(text, False) text = process_text(text, False)

@ -3,14 +3,17 @@ import os
import re import re
import tempfile import tempfile
import threading import threading
import textwrap
import time import time
from pathlib import Path
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 Final
from typing import Tuple, Dict from typing import Tuple, Dict
import ffmpeg import ffmpeg
import translators import translators
from PIL import Image from PIL import ImageDraw, ImageFont, Image
from rich.console import Console from rich.console import Console
from rich.progress import track from rich.progress import track
@ -105,6 +108,41 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str:
exit(1) exit(1)
return output_path return output_path
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): def merge_background_audio(audio: ffmpeg, reddit_id: str):
"""Gather an audio and merge with assets/backgrounds/background.mp3 """Gather an audio and merge with assets/backgrounds/background.mp3
@ -201,6 +239,28 @@ def make_final_video(
image_clips = list() image_clips = list()
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"]
title = name_normalize(title)
font_color = "#000000"
padding = 5
# create_fancy_thumbnail(image, text, text_color, padding
title_img = create_fancy_thumbnail(
title_template, title, font_color, padding
)
title_img.save(f"assets/temp/{reddit_id}/png/title.png")
# Copyright end
image_clips.insert( image_clips.insert(
0, 0,
ffmpeg.input(f"assets/temp/{reddit_id}/png/title.png")["v"].filter( ffmpeg.input(f"assets/temp/{reddit_id}/png/title.png")["v"].filter(

@ -58,6 +58,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
bgcolor = (255, 255, 255, 255) bgcolor = (255, 255, 255, 255)
txtcolor = (0, 0, 0) txtcolor = (0, 0, 0)
transparent = False transparent = False
if storymode and settings.config["settings"]["storymodemethod"] == 1: if storymode and settings.config["settings"]["storymodemethod"] == 1:
# for idx,item in enumerate(reddit_object["thread_post"]): # for idx,item in enumerate(reddit_object["thread_post"]):
print_substep("Generating images...") print_substep("Generating images...")
@ -73,7 +74,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
print_substep("Launching Headless Browser...") print_substep("Launching Headless Browser...")
browser = p.chromium.launch( browser = p.chromium.launch(
headless=True headless=False
) # headless=False will show the browser for debugging purposes ) # headless=False will show the browser for debugging purposes
# Device scale factor (or dsf for short) allows us to increase the resolution of the screenshots # Device scale factor (or dsf for short) allows us to increase the resolution of the screenshots
# When the dsf is 1, the width of the screenshot is 600 pixels # When the dsf is 1, the width of the screenshot is 600 pixels
@ -98,9 +99,9 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
page.set_viewport_size(ViewportSize(width=1920, height=1080)) page.set_viewport_size(ViewportSize(width=1920, height=1080))
page.wait_for_load_state() page.wait_for_load_state()
page.locator('[name="username"]').fill(settings.config["reddit"]["creds"]["username"]) page.locator(f'input[name="username"]').fill(settings.config["reddit"]["creds"]["username"])
page.locator('[name="password"]').fill(settings.config["reddit"]["creds"]["password"]) page.locator(f'input[name="password"]').fill(settings.config["reddit"]["creds"]["password"])
page.locator("button[class$='m-full-width']").click() page.get_by_role("button", name="Log In").click()
page.wait_for_timeout(5000) page.wait_for_timeout(5000)
login_error_div = page.locator(".AnimatedForm__errorMessage").first login_error_div = page.locator(".AnimatedForm__errorMessage").first
@ -218,7 +219,7 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
if page.locator('[data-testid="content-gate"]').is_visible(): if page.locator('[data-testid="content-gate"]').is_visible():
page.locator('[data-testid="content-gate"] button').click() page.locator('[data-testid="content-gate"] button').click()
page.goto(f'https://reddit.com{comment["comment_url"]}', timeout=0) page.goto(f"https://new.reddit.com/{comment['comment_url']}")
# translate code # translate code

Loading…
Cancel
Save