Version 3.2
The RedditVideoMakerBot has been updated to version 3.2, bringing exciting new features and bug fixes. Introducing **ElevenLabs TTS** for high-quality audio. Enjoy **background audio** and **random voices per comment**. Run the bot with one click using the **bat file**. Use the **zoom setting** for bigger text. Bug fixes include video downloader improvements, random story mode fix, updated dependencies, code optimizations, text size adjustments, enhanced Reddit credentials validation, and translator fixes. Enjoy the new features and **thanks to all contributors**!
This commit is contained in:
1 parent
f2d89a10dd
commit
0ea74e43f1
24 files changed
+539
-222
No files matched your search
+105
-42
@@ -3,29 +3,36 @@ import random
|
||||
import re
|
||||
from pathlib import Path
|
||||
from random import randrange
|
||||
from typing import Any, Tuple
|
||||
from typing import Any, Tuple, Dict
|
||||
|
||||
from moviepy.editor import VideoFileClip
|
||||
from moviepy.editor import VideoFileClip, AudioFileClip
|
||||
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
|
||||
from pytube import YouTube
|
||||
from pytube.cli import on_progress
|
||||
from utils import settings
|
||||
from utils.console import print_step, print_substep
|
||||
import yt_dlp
|
||||
|
||||
# Load background videos
|
||||
with open("./utils/backgrounds.json") as json_file:
|
||||
background_options = json.load(json_file)
|
||||
|
||||
# Remove "__comment" from backgrounds
|
||||
background_options.pop("__comment", None)
|
||||
def load_background_options():
|
||||
background_options = {}
|
||||
# Load background videos
|
||||
with open("./utils/background_videos.json") as json_file:
|
||||
background_options["video"] = json.load(json_file)
|
||||
|
||||
# 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.keys()):
|
||||
pos = background_options[name][3]
|
||||
# Load background audios
|
||||
with open("./utils/background_audios.json") as json_file:
|
||||
background_options["audio"] = json.load(json_file)
|
||||
|
||||
if pos != "center":
|
||||
background_options[name][3] = lambda t: ("center", pos + t)
|
||||
# Remove "__comment" from backgrounds
|
||||
del background_options["video"]["__comment"]
|
||||
del background_options["audio"]["__comment"]
|
||||
|
||||
for name in list(background_options["video"].keys()):
|
||||
pos = background_options["video"][name][3]
|
||||
|
||||
if pos != "center":
|
||||
background_options["video"][name][3] = lambda t: ("center", pos + t)
|
||||
|
||||
return background_options
|
||||
|
||||
|
||||
def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]:
|
||||
@@ -38,15 +45,22 @@ def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int
|
||||
Returns:
|
||||
tuple[int,int]: Start and end time of the randomized interval
|
||||
"""
|
||||
random_time = randrange(180, int(length_of_clip) - int(video_length))
|
||||
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:
|
||||
raise Exception("Your background is too short for this video length")
|
||||
else:
|
||||
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
|
||||
|
||||
|
||||
def get_background_config():
|
||||
def get_background_config(mode: str):
|
||||
"""Fetch the background/s configuration"""
|
||||
try:
|
||||
choice = str(
|
||||
settings.config["settings"]["background"]["background_choice"]
|
||||
settings.config["settings"]["background"][f"background_{mode}"]
|
||||
).casefold()
|
||||
except AttributeError:
|
||||
print_substep("No background selected. Picking random background'")
|
||||
@@ -54,57 +68,106 @@ def get_background_config():
|
||||
|
||||
# Handle default / not supported background using default option.
|
||||
# Default : pick random from supported background.
|
||||
if not choice or choice not in background_options:
|
||||
choice = random.choice(list(background_options.keys()))
|
||||
if not choice or choice not in background_options[mode]:
|
||||
choice = random.choice(list(background_options[mode].keys()))
|
||||
|
||||
return background_options[choice]
|
||||
return background_options[mode][choice]
|
||||
|
||||
|
||||
def download_background(background_config: Tuple[str, str, str, Any]):
|
||||
def download_background_video(background_config: Tuple[str, str, str, Any]):
|
||||
"""Downloads the background/s video from YouTube."""
|
||||
Path("./assets/backgrounds/").mkdir(parents=True, exist_ok=True)
|
||||
Path("./assets/backgrounds/video/").mkdir(parents=True, exist_ok=True)
|
||||
# note: make sure the file name doesn't include an - in it
|
||||
uri, filename, credit, _ = background_config
|
||||
if Path(f"assets/backgrounds/{credit}-{filename}").is_file():
|
||||
if Path(f"assets/backgrounds/video/{credit}-{filename}").is_file():
|
||||
return
|
||||
print_step(
|
||||
"We need to download the backgrounds videos. they are fairly large but it's only done once. 😎"
|
||||
)
|
||||
print_substep("Downloading the backgrounds videos... please be patient 🙏 ")
|
||||
print_substep(f"Downloading {filename} from {uri}")
|
||||
YouTube(uri, on_progress_callback=on_progress).streams.filter(
|
||||
res="1080p"
|
||||
).first().download("assets/backgrounds", filename=f"{credit}-{filename}")
|
||||
ydl_opts = {
|
||||
"format": "bestvideo[height<=1080][ext=mp4]",
|
||||
"outtmpl": f"assets/backgrounds/video/{credit}-{filename}",
|
||||
"retries": 10,
|
||||
}
|
||||
|
||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||
ydl.download(uri)
|
||||
print_substep("Background video downloaded successfully! 🎉", style="bold green")
|
||||
|
||||
|
||||
def chop_background_video(
|
||||
background_config: Tuple[str, str, str, Any], video_length: int, reddit_object: dict
|
||||
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)
|
||||
# note: make sure the file name doesn't include an - in it
|
||||
uri, filename, credit = background_config
|
||||
if Path(f"assets/backgrounds/audio/{credit}-{filename}").is_file():
|
||||
return
|
||||
print_step(
|
||||
"We need to download the backgrounds audio. they are fairly large but it's only done once. 😎"
|
||||
)
|
||||
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,
|
||||
}
|
||||
|
||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||
ydl.download([uri])
|
||||
|
||||
print_substep("Background audio downloaded successfully! 🎉", style="bold green")
|
||||
|
||||
|
||||
def chop_background(
|
||||
background_config: Dict[str, Tuple], video_length: int, reddit_object: dict
|
||||
):
|
||||
"""Generates the background footage to be used in the video and writes it to assets/temp/background.mp4
|
||||
"""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
|
||||
|
||||
Args:
|
||||
background_config (Tuple[str, str, str, Any]) : Current background configuration
|
||||
background_config (Dict[str,Tuple]]) : Current background configuration
|
||||
video_length (int): Length of the clip where the background footage is to be taken out of
|
||||
"""
|
||||
id = re.sub(r"[^\w\s-]", "", reddit_object["thread_id"])
|
||||
|
||||
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]}"
|
||||
)
|
||||
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)
|
||||
background_audio.write_audiofile(f"assets/temp/{id}/background.mp3")
|
||||
|
||||
print_step("Finding a spot in the backgrounds video to chop...✂️")
|
||||
choice = f"{background_config[2]}-{background_config[1]}"
|
||||
id = re.sub(r"[^\w\s-]", "", reddit_object["thread_id"])
|
||||
background = VideoFileClip(f"assets/backgrounds/{choice}")
|
||||
|
||||
start_time, end_time = get_start_and_end_times(video_length, background.duration)
|
||||
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
|
||||
)
|
||||
# Extract video subclip
|
||||
try:
|
||||
ffmpeg_extract_subclip(
|
||||
f"assets/backgrounds/{choice}",
|
||||
start_time,
|
||||
end_time,
|
||||
f"assets/backgrounds/video/{video_choice}",
|
||||
start_time_video,
|
||||
end_time_video,
|
||||
targetname=f"assets/temp/{id}/background.mp4",
|
||||
)
|
||||
except (OSError, IOError): # ffmpeg issue see #348
|
||||
print_substep("FFMPEG issue. Trying again...")
|
||||
with VideoFileClip(f"assets/backgrounds/{choice}") as video:
|
||||
new = video.subclip(start_time, end_time)
|
||||
with VideoFileClip(f"assets/backgrounds/video/{video_choice}") as video:
|
||||
new = video.subclip(start_time_video, end_time_video)
|
||||
new.write_videofile(f"assets/temp/{id}/background.mp4")
|
||||
print_substep("Background video chopped successfully!", style="bold green")
|
||||
return background_config[2]
|
||||
return background_config["video"][2]
|
||||
|
||||
|
||||
# Create a tuple for downloads background (background_audio_options, background_video_options)
|
||||
background_options = load_background_options()
|
||||
+103
-26
@@ -1,29 +1,28 @@
|
||||
import multiprocessing
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
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
|
||||
from typing import Tuple, Any, Dict
|
||||
|
||||
import ffmpeg
|
||||
import translators as ts
|
||||
import translators
|
||||
from PIL import Image
|
||||
from rich.console import Console
|
||||
from rich.progress import track
|
||||
|
||||
from utils import settings
|
||||
from utils.cleanup import cleanup
|
||||
from utils.console import print_step, print_substep
|
||||
from utils.thumbnail import create_thumbnail
|
||||
from utils.videos import save_data
|
||||
|
||||
console = Console()
|
||||
from utils import settings
|
||||
|
||||
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
|
||||
@@ -98,17 +97,39 @@ def prepare_background(reddit_id: str, W: int, H: int) -> str:
|
||||
)
|
||||
try:
|
||||
output.run(quiet=True)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
exit()
|
||||
except ffmpeg.Error as e:
|
||||
print(e.stderr.decode("utf8"))
|
||||
exit(1)
|
||||
return output_path
|
||||
|
||||
|
||||
def merge_background_audio(audio: ffmpeg, reddit_id: str):
|
||||
"""Gather an audio and merge with assets/backgrounds/background.mp3
|
||||
Args:
|
||||
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
|
||||
else:
|
||||
# sets volume to config
|
||||
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
|
||||
|
||||
|
||||
def make_final_video(
|
||||
number_of_clips: int,
|
||||
length: int,
|
||||
reddit_obj: dict,
|
||||
background_config: Tuple[str, str, str, Any],
|
||||
background_config: Dict[str, Tuple],
|
||||
):
|
||||
"""Gathers audio clips, gathers all screenshots, stitches them together and saves the final video to assets/temp
|
||||
Args:
|
||||
@@ -121,13 +142,26 @@ def make_final_video(
|
||||
W: Final[int] = int(settings.config["settings"]["resolution_w"])
|
||||
H: Final[int] = int(settings.config["settings"]["resolution_h"])
|
||||
|
||||
opacity = settings.config["settings"]["opacity"]
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
print_step("Creating the final video 🎥")
|
||||
|
||||
background_clip = ffmpeg.input(prepare_background(reddit_id, W=W, H=H))
|
||||
|
||||
# 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'
|
||||
exit()
|
||||
if settings.config["settings"]["storymode"]:
|
||||
if settings.config["settings"]["storymodemethod"] == 0:
|
||||
audio_clips = [ffmpeg.input(f"assets/temp/{reddit_id}/mp3/title.mp3")]
|
||||
@@ -177,6 +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)
|
||||
|
||||
image_clips = list()
|
||||
|
||||
@@ -242,8 +277,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",
|
||||
@@ -258,15 +294,25 @@ def make_final_video(
|
||||
subreddit = settings.config["reddit"]["thread"]["subreddit"]
|
||||
|
||||
if not exists(f"./results/{subreddit}"):
|
||||
print_substep("The results folder didn't exist so I made it")
|
||||
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."
|
||||
)
|
||||
os.makedirs(f"./results/{subreddit}/OnlyTTS")
|
||||
|
||||
# create a thumbnail for the video
|
||||
settingsbackground = settings.config["settings"]["background"]
|
||||
|
||||
if settingsbackground["background_thumbnail"]:
|
||||
if not exists(f"./results/{subreddit}/thumbnails"):
|
||||
print_substep("The results/thumbnails folder didn't exist so I made it")
|
||||
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(
|
||||
@@ -300,34 +346,36 @@ def make_final_video(
|
||||
f"Thumbnail - Building Thumbnail in assets/temp/{reddit_id}/thumbnail.png"
|
||||
)
|
||||
|
||||
text = f"Background by {background_config[2]}"
|
||||
text = f"Background by {background_config['video'][2]}"
|
||||
background_clip = ffmpeg.drawtext(
|
||||
background_clip,
|
||||
text=text,
|
||||
x=f"(w-text_w)",
|
||||
y=f"(h-text_h)",
|
||||
fontsize=12,
|
||||
fontsize=5,
|
||||
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
|
||||
|
||||
pbar = tqdm(total=100, desc="Progress: ", bar_format="{l_bar}{bar}", unit=" %")
|
||||
|
||||
def on_update_example(progress):
|
||||
def on_update_example(progress) -> None:
|
||||
status = round(progress * 100, 2)
|
||||
old_percentage = pbar.n
|
||||
pbar.update(status - old_percentage)
|
||||
|
||||
path = f"results/{subreddit}/{filename}"
|
||||
path = path[:251]
|
||||
path = path + ".mp4"
|
||||
|
||||
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.
|
||||
ffmpeg.output(
|
||||
background_clip,
|
||||
audio,
|
||||
final_audio,
|
||||
path,
|
||||
f="mp4",
|
||||
**{
|
||||
@@ -342,12 +390,41 @@ def make_final_video(
|
||||
capture_stdout=False,
|
||||
capture_stderr=False,
|
||||
)
|
||||
|
||||
old_percentage = pbar.n
|
||||
pbar.update(100 - old_percentage)
|
||||
pbar.close()
|
||||
if allowOnlyTTSFolder:
|
||||
path = defaultPath + f"/OnlyTTS/{filename}"
|
||||
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:
|
||||
try:
|
||||
ffmpeg.output(
|
||||
background_clip,
|
||||
audio,
|
||||
path,
|
||||
f="mp4",
|
||||
**{
|
||||
"c:v": "h264",
|
||||
"b:v": "20M",
|
||||
"b:a": "192k",
|
||||
"threads": multiprocessing.cpu_count(),
|
||||
},
|
||||
).overwrite_output().global_args("-progress", progress.output_file.name).run(
|
||||
quiet=True,
|
||||
overwrite_output=True,
|
||||
capture_stdout=False,
|
||||
capture_stderr=False,
|
||||
)
|
||||
except ffmpeg.Error as e:
|
||||
print(e.stderr.decode("utf8"))
|
||||
exit(1)
|
||||
|
||||
save_data(subreddit, filename + ".mp4", title, idx, background_config[2])
|
||||
old_percentage = pbar.n
|
||||
pbar.update(100 - old_percentage)
|
||||
pbar.close()
|
||||
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 🗑")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -116,7 +117,30 @@ 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()
|
||||
if login_error_message.strip() == "":
|
||||
# The div element is empty, no error
|
||||
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",
|
||||
)
|
||||
exit()
|
||||
else:
|
||||
pass
|
||||
|
||||
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))
|
||||
@@ -144,13 +168,13 @@ 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,
|
||||
)
|
||||
|
||||
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:
|
||||
@@ -158,9 +182,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(
|
||||
@@ -202,10 +237,10 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
|
||||
|
||||
page.goto(f'https://reddit.com{comment["comment_url"]}', timeout=0)
|
||||
|
||||
# translate code
|
||||
# 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"],
|
||||
)
|
||||
@@ -214,9 +249,29 @@ 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))
|
||||
# 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:
|
||||
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
|
||||
@@ -227,3 +282,4 @@ def get_screenshots_of_reddit_posts(reddit_object: dict, screenshot_num: int):
|
||||
browser.close()
|
||||
|
||||
print_substep("Screenshots downloaded Successfully.", style="bold green")
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user