Merge branch 'develop' into joshholly-fix-opacity
This commit is contained in:
11 files changed
+233
-77
No files matched your search
@@ -70,7 +70,7 @@ In its current state, this bot does exactly what it needs to do. However, improv
|
||||
I have tried to simplify the code so anyone can read it and start contributing at any skill level. Don't be shy :) contribute!
|
||||
|
||||
- [ ] Creating better documentation and adding a command line interface.
|
||||
- [ ] Allowing the user to choose background music for their videos.
|
||||
- [x] Allowing the user to choose background music for their videos.
|
||||
- [x] Allowing users to choose a reddit thread instead of being randomized.
|
||||
- [x] Allowing users to choose a background that is picked instead of the Minecraft one.
|
||||
- [x] Allowing users to choose between any subreddit.
|
||||
|
||||
@@ -55,9 +55,20 @@ class TTSEngine:
|
||||
self,
|
||||
): # adds periods to the end of paragraphs (where people often forget to put them) so tts doesn't blend sentences
|
||||
for comment in self.reddit_object["comments"]:
|
||||
# remove links
|
||||
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"])
|
||||
if comment["comment_body"][-1] != ".":
|
||||
comment["comment_body"] += "."
|
||||
comment["comment_body"] = comment["comment_body"].replace(". . .", ".")
|
||||
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)
|
||||
|
||||
@@ -6,6 +6,7 @@ from os import name
|
||||
from pathlib import Path
|
||||
from subprocess import Popen
|
||||
|
||||
import ffmpeg
|
||||
from prawcore import ResponseException
|
||||
from utils.console import print_substep
|
||||
from reddit.subreddit import get_subreddit_threads
|
||||
@@ -15,8 +16,9 @@ from utils.console import print_markdown, print_step
|
||||
from utils.id import id
|
||||
from utils.version import checkversion
|
||||
from video_creation.background import (
|
||||
download_background,
|
||||
chop_background_video,
|
||||
download_background_video,
|
||||
download_background_audio,
|
||||
chop_background,
|
||||
get_background_config,
|
||||
)
|
||||
from video_creation.final_video import make_final_video
|
||||
@@ -50,10 +52,18 @@ def main(POST_ID=None) -> None:
|
||||
length, number_of_comments = save_text_to_mp3(reddit_object)
|
||||
length = math.ceil(length)
|
||||
get_screenshots_of_reddit_posts(reddit_object, number_of_comments)
|
||||
bg_config = get_background_config()
|
||||
download_background(bg_config)
|
||||
chop_background_video(bg_config, length, reddit_object)
|
||||
make_final_video(number_of_comments, length, reddit_object, bg_config)
|
||||
bg_config = {
|
||||
"video": get_background_config("video"),
|
||||
"audio": get_background_config("audio"),
|
||||
}
|
||||
download_background_video(bg_config["video"])
|
||||
download_background_audio(bg_config["audio"])
|
||||
chop_background(bg_config, length, reddit_object)
|
||||
try:
|
||||
make_final_video(number_of_comments, length, reddit_object, bg_config)
|
||||
except ffmpeg.Error as e:
|
||||
print(e.stderr.decode("utf8"))
|
||||
exit(1)
|
||||
|
||||
|
||||
def run_many(times) -> None:
|
||||
@@ -81,6 +91,7 @@ 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.")
|
||||
exit()
|
||||
ffmpeg_install() # install ffmpeg if not installed
|
||||
directory = Path().absolute()
|
||||
config = settings.check_toml(
|
||||
@@ -127,4 +138,4 @@ if __name__ == "__main__":
|
||||
f"Error: {err} \n"
|
||||
f'Config: {config["settings"]}'
|
||||
)
|
||||
raise err
|
||||
raise err
|
||||
+5
-5
@@ -5,18 +5,18 @@ moviepy==1.0.3
|
||||
playwright==1.23.0
|
||||
praw==7.6.1
|
||||
prawcore~=2.3.0
|
||||
pytube==12.1.0
|
||||
requests==2.28.1
|
||||
rich==13.3.1
|
||||
rich==13.3.5
|
||||
toml==0.10.2
|
||||
translators==5.3.1
|
||||
pyttsx3==2.90
|
||||
Pillow~=9.4.0
|
||||
tomlkit==0.11.4
|
||||
Flask==2.2.2
|
||||
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
|
||||
ffmpeg-python==0.2.0
|
||||
ffmpeg-python==0.2.0
|
||||
yt-dlp==2023.3.4
|
||||
@@ -33,20 +33,21 @@ 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" }
|
||||
|
||||
[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" }
|
||||
#background_audio = { optional = true, type = "bool", default = false, example = false, options = [true, false,], explanation = "Sets a audio to play in the background (put a background.mp3 file in the assets/backgrounds directory for it to be used.)" }
|
||||
#background_audio_volume = { optional = true, type = "float", default = 0.3, example = 0.1, explanation="Sets the volume of the background audio. only used if the background_audio is also set to true" }
|
||||
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_audio = { optional = true, default = "lofi", example = "chill-summer", options = ["lofi","lofi-2","chill-summer",""], explanation = "Sets the background audio for the video" }
|
||||
background_audio_volume = { optional = true, type = "float", nmin = 0, nmax = 1, default = 0.15, example = 0.05, explanation="Sets the volume of the background audio. If you don't want background audio, set it to 0.", oob_error = "The volume HAS to be between 0 and 1", input_error = "The volume HAS to be a float number between 0 and 1"}
|
||||
enable_extra_audio = { optional = true, type = "bool", default = false, example = false, explanation="Used if you want to render another video without background audio in a separate folder", input_error = "The value HAS to be true or false"}
|
||||
background_thumbnail = { optional = true, type = "bool", default = false, example = false, options = [true, false,], explanation = "Generate a thumbnail for the video (put a thumbnail.png file in the assets/backgrounds directory.)" }
|
||||
background_thumbnail_font_family = { optional = true, default = "arial", example = "arial", explanation = "Font family for the thumbnail text" }
|
||||
background_thumbnail_font_size = { optional = true, type = "int", default = 96, example = 96, explanation = "Font size in pixels for the thumbnail text" }
|
||||
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 = "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." }
|
||||
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" }
|
||||
tiktok_sessionid = { optional = true, example = "c76bcc3a7625abcc27b508c7db457ff1", explanation = "TikTok sessionid needed for the TTS API request. Check documentation if you don't know how to obtain it." }
|
||||
tiktok_sessionid = { optional = true, example = "c76bcc3a7625abcc27b508c7db457ff1", explanation = "TikTok sessionid needed if you're using the TikTok TTS. Check documentation if you don't know how to obtain it." }
|
||||
python_voice = { optional = false, default = "1", example = "1", explanation = "The index of the system tts voices (can be downloaded externally, run ptt.py to find value, start from zero)" }
|
||||
py_voice_num = { optional = false, default = "2", example = "2", explanation = "The number of system voices (2 are pre-installed in Windows)" }
|
||||
silence_duration = { optional = true, example = "0.1", explanation = "Time in seconds between TTS comments", default = 0.3, type = "float" }
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"__comment": "Supported Backgrounds Audio. Can add/remove background audio here...",
|
||||
"lofi": [
|
||||
"https://www.youtube.com/watch?v=LTphVIore3A",
|
||||
"lofi.mp3",
|
||||
"Super Lofi World"
|
||||
],
|
||||
"lofi-2":[
|
||||
"https://www.youtube.com/watch?v=BEXL80LS0-I",
|
||||
"lofi-2.mp3",
|
||||
"stompsPlaylist"
|
||||
],
|
||||
"chill-summer":[
|
||||
"https://www.youtube.com/watch?v=EZE8JagnBI8",
|
||||
"chill-summer.mp3",
|
||||
"Mellow Vibes Radio"
|
||||
]
|
||||
}
|
||||
File renamed without changes.
@@ -68,9 +68,9 @@ def imagemaker(theme, reddit_obj: dict, txtclr, padding=5, transparent=False) ->
|
||||
tfont = ImageFont.truetype(os.path.join("fonts", "Roboto-Bold.ttf"), 50)
|
||||
else:
|
||||
tfont = ImageFont.truetype(
|
||||
os.path.join("fonts", "Roboto-Bold.ttf"), 35
|
||||
os.path.join("fonts", "Roboto-Bold.ttf"), 100
|
||||
) # for title
|
||||
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 30)
|
||||
font = ImageFont.truetype(os.path.join("fonts", "Roboto-Regular.ttf"), 90)
|
||||
size = (1920, 1080)
|
||||
|
||||
image = Image.new("RGBA", size, theme)
|
||||
|
||||
@@ -3,29 +3,38 @@ 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)
|
||||
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)
|
||||
|
||||
# Remove "__comment" from backgrounds
|
||||
background_options.pop("__comment", None)
|
||||
# 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()):
|
||||
pos = background_options["video"][name][3]
|
||||
|
||||
# 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]
|
||||
if pos != "center":
|
||||
background_options["video"][name][3] = lambda t: ("center", pos + t)
|
||||
|
||||
return background_options
|
||||
|
||||
if pos != "center":
|
||||
background_options[name][3] = lambda t: ("center", pos + t)
|
||||
|
||||
|
||||
def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int, int]:
|
||||
@@ -42,11 +51,11 @@ def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int
|
||||
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 +63,98 @@ 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 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,
|
||||
}
|
||||
|
||||
def chop_background_video(
|
||||
background_config: Tuple[str, str, str, Any], video_length: int, reddit_object: dict
|
||||
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()
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
import shutil
|
||||
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
|
||||
@@ -103,12 +103,34 @@ 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:
|
||||
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:
|
||||
@@ -123,6 +145,10 @@ def make_final_video(
|
||||
opacity = int(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))
|
||||
@@ -178,6 +204,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()
|
||||
|
||||
@@ -260,15 +287,19 @@ 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(
|
||||
@@ -302,7 +333,7 @@ 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,
|
||||
@@ -322,15 +353,14 @@ def make_final_video(
|
||||
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,
|
||||
path,
|
||||
final_audio,
|
||||
path,
|
||||
f="mp4",
|
||||
**{
|
||||
"c:v": "h264",
|
||||
@@ -344,13 +374,35 @@ def make_final_video(
|
||||
capture_stdout=False,
|
||||
capture_stderr=False,
|
||||
)
|
||||
|
||||
old_percentage = pbar.n
|
||||
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.
|
||||
print_step("Rendering the Only TTS Video 🎥")
|
||||
with ProgressFfmpeg(length, on_update_example) as progress:
|
||||
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,
|
||||
)
|
||||
old_percentage = pbar.n
|
||||
pbar.update(100 - old_percentage)
|
||||
pbar.close()
|
||||
path = r"~/Library/Mobile Documents/com~apple~CloudDocs/reddit/"
|
||||
save_data(path+subreddit, filename + ".mp4", title, idx, background_config[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 🗑")
|
||||
print_step("Done! 🎉 The video is in the results folder 📁")
|
||||
print_step("Done! 🎉 The video is in the results folder 📁")
|
||||
@@ -115,6 +115,19 @@ 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()
|
||||
# Get the thread screenshot
|
||||
|
||||
Reference in new issue
Block a user