You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RedditVideoMakerBot/utils/imagenarator.py

108 lines
4.4 KiB

import re
import textwrap
import os
import json
from utils import settings
from PIL import Image, ImageDraw, ImageFont
from rich.progress import track
from TTS.engine_wrapper import process_text
from utils.console import print_substep
def load_text_replacements():
text_replacements = {}
# Load background videos
with open("./utils/text_replacements.json") as json_file:
text_replacements = json.load(json_file)
del text_replacements["__comment"]
return text_replacements
def perform_text_replacements(text):
updated_text = text
for replacement in text_replacements['text-and-audio']:
regex_escaped_word=re.escape(replacement[0])
compiled = re.compile(r"\b{}\b".format(regex_escaped_word), re.IGNORECASE)
updated_text = compiled.sub(replacement[1], updated_text)
for replacement in text_replacements['text-only']:
compiled = re.compile(r"\b{}\b".format(regex_escaped_word), re.IGNORECASE)
updated_text = compiled.sub(replacement[1], updated_text)
return updated_text
def draw_multiple_line_text(
image, text, font, text_color, padding, wrap=50, transparent=False
) -> None:
"""
Draw multiline text over given image
"""
draw = ImageDraw.Draw(image)
Fontperm = font.getsize(text)
image_width, image_height = image.size
lines = textwrap.wrap(text, width=wrap)
y = (image_height / 2) - (((Fontperm[1] + (len(lines) * padding) / len(lines)) * len(lines)) / 2)
for line in lines:
line_width, line_height = font.getsize(line)
if transparent:
shadowcolor = "black"
for i in range(1, 5):
draw.text(
((image_width - line_width) / 2 - i, y - i),
line,
font=font,
fill=shadowcolor,
)
draw.text(
((image_width - line_width) / 2 + i, y - i),
line,
font=font,
fill=shadowcolor,
)
draw.text(
((image_width - line_width) / 2 - i, y + i),
line,
font=font,
fill=shadowcolor,
)
draw.text(
((image_width - line_width) / 2 + i, y + i),
line,
font=font,
fill=shadowcolor,
)
draw.text(((image_width - line_width) / 2, y), line, font=font, fill=text_color)
y += line_height + padding
def imagemaker(theme, reddit_obj: dict, txtclr, transparent=False) -> None:
"""
Render Images for video
"""
title = process_text(perform_text_replacements(reddit_obj["thread_title"]), False)
texts = reddit_obj["thread_post"]
id = re.sub(r"[^\w\s-]", "", reddit_obj["thread_id"])
if transparent:
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), int(settings.config["settings"]["text_size"])) # changed
tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), int(settings.config["settings"]["text_size"])) # changed
else:
tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), int(settings.config["settings"]["text_size"])) # for title # changed
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), int(settings.config["settings"]["text_size"])) # changed
size = (int(settings.config["settings"]["resolution_w"]), int(settings.config["settings"]["resolution_h"]))
image = Image.new("RGBA", size, theme)
# for title
draw_multiple_line_text(image, perform_text_replacements(title), tfont, txtclr, int(settings.config["settings"]["text_padding"]), wrap=int(settings.config["settings"]["text_wrap"]), transparent=transparent)
image.save(f"assets/temp/{id}/png/title.png")
for idx, text in track(enumerate(texts), "💬 Rendering captions...", total=len(texts)):
image = Image.new("RGBA", size, theme)
text = process_text(text, False)
draw_multiple_line_text(image, perform_text_replacements(text), font, txtclr, int(settings.config["settings"]["text_padding"]), wrap=int(settings.config["settings"]["text_wrap"]), transparent=transparent)
image.save(f"assets/temp/{id}/png/img{idx}.png")
print_substep("Captions rendered successfully!", style="bold green")
text_replacements = load_text_replacements()