diff --git a/.config.template.toml b/.config.template.toml
index ddfa293..18f1b00 100644
--- a/.config.template.toml
+++ b/.config.template.toml
@@ -12,11 +12,11 @@ password = { optional = false, nmin = 8, explanation = "the password of your red
random = { optional = true, options = [true,
false,
], default = false, type = "bool", explanation = "If set to no, it will ask you a thread link to extract the thread, if yes it will randomize it. Default: 'False'", example = "True" }
-subreddit = { optional = false, regex = "[_0-9a-zA-Z]+$", nmin = 3, nmax = 21, explanation = "what subreddit to pull posts from, the name of the sub, not the URL", example = "AskReddit", oob_error = "A subreddit name HAS to be between 3 and 20 characters" }
+subreddit = { optional = false, regex = "[_0-9a-zA-Z]+$", nmin = 3, explanation = "what subreddit to pull posts from, the name of the sub, not the URL", example = "AskReddit", oob_error = "A subreddit name HAS to be between 3 and 20 characters" }
post_id = { optional = true, default = "", regex = "^((?!://|://)[+a-zA-Z])*$", explanation = "Used if you want to use a specific post.", example = "urdtfx" }
max_comment_length = { default = 500, optional = false, nmin = 10, nmax = 10000, type = "int", explanation = "max number of characters a comment can have. default is 500", example = 500, oob_error = "the max comment length should be between 10 and 10000" }
post_lang = { default = "", optional = true, explanation = "The language you would like to translate to.", example = "es-cr" }
-
+min_comments = { default = 20, optional = false, nmin = 15, type = "int", explanation = "The minimum number of comments a post should have to be included. default is 20", example = 29, oob_error = "the minimum number of comments should be between 15 and 999999" }
[settings]
allow_nsfw = { optional = false, type = "bool", default = false, example = false, options = [true,
false,
@@ -29,10 +29,15 @@ opacity = { optional = false, default = 0.9, example = 0.8, explanation = "Sets
storymode = { optional = true, type = "bool", default = false, example = false, options = [true,
false,
], explanation = "not yet implemented" }
+
+[settings.background]
background_choice = { optional = true, default = "minecraft", example = "minecraft", options = ["minecraft", "gta", "rocket-league", "motor-gta", ""], explanation = "Sets the background for the video" }
-background_audio = { optional = true, type = "bool", default = false, example = false, options = [true,
- false,
-], explaination="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 = { optional = true, type = "bool", default = false, example = false, options = [true,
+# false,
+#], explaination="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" }
+
+
[settings.tts]
choice = { optional = false, default = "", options = ["streamlabspolly", "tiktok", "googletranslate", "awspolly", ], example = "streamlabspolly", explanation = "The backend 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" }
diff --git a/GUI/index.html b/GUI/index.html
new file mode 100644
index 0000000..807c9e7
--- /dev/null
+++ b/GUI/index.html
@@ -0,0 +1,281 @@
+
+
+
+
+
+ RedditVideoMakerBot
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 57aa6d4..cb82738 100644
--- a/README.md
+++ b/README.md
@@ -88,3 +88,5 @@ CallumIO (c.#6837) - https://github.com/CallumIO
Verq (Verq#2338) - https://github.com/CordlessCoder
LukaHietala (Pix.#0001) - https://github.com/LukaHietala
+
+Freebiell (Freebie#6429) - https://github.com/FreebieII
diff --git a/TTS/aws_polly.py b/TTS/aws_polly.py
index 13eaea1..efd762b 100644
--- a/TTS/aws_polly.py
+++ b/TTS/aws_polly.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
from boto3 import Session
-from botocore.exceptions import BotoCoreError, ClientError
+from botocore.exceptions import BotoCoreError, ClientError, ProfileNotFound
import sys
from utils import settings
import random
@@ -30,36 +30,46 @@ class AWSPolly:
self.voices = voices
def run(self, text, filepath, random_voice: bool = False):
- session = Session(profile_name="polly")
- polly = session.client("polly")
- if random_voice:
- voice = self.randomvoice()
- else:
- if not settings.config["settings"]["tts"]["aws_polly_voice"]:
- return ValueError(
- f"Please set the TOML variable AWS_VOICE to a valid voice. options are: {voices}"
- )
- voice = str(settings.config["settings"]["tts"]["aws_polly_voice"]).capitalize()
try:
- # Request speech synthesis
- response = polly.synthesize_speech(
- Text=text, OutputFormat="mp3", VoiceId=voice, Engine="neural"
- )
- except (BotoCoreError, ClientError) as error:
- # The service returned an error, exit gracefully
- print(error)
- sys.exit(-1)
+ session = Session(profile_name="polly")
+ polly = session.client("polly")
+ if random_voice:
+ voice = self.randomvoice()
+ else:
+ if not settings.config["settings"]["tts"]["aws_polly_voice"]:
+ raise ValueError(
+ f"Please set the TOML variable AWS_VOICE to a valid voice. options are: {voices}"
+ )
+ voice = str(settings.config["settings"]["tts"]["aws_polly_voice"]).capitalize()
+ try:
+ # Request speech synthesis
+ response = polly.synthesize_speech(
+ Text=text, OutputFormat="mp3", VoiceId=voice, Engine="neural"
+ )
+ except (BotoCoreError, ClientError) as error:
+ # The service returned an error, exit gracefully
+ print(error)
+ sys.exit(-1)
- # Access the audio stream from the response
- if "AudioStream" in response:
- file = open(filepath, "wb")
- file.write(response["AudioStream"].read())
- file.close()
- # print_substep(f"Saved Text {idx} to MP3 files successfully.", style="bold green")
+ # Access the audio stream from the response
+ if "AudioStream" in response:
+ file = open(filepath, "wb")
+ file.write(response["AudioStream"].read())
+ file.close()
+ # print_substep(f"Saved Text {idx} to MP3 files successfully.", style="bold green")
- else:
- # The response didn't contain audio data, exit gracefully
- print("Could not stream audio")
+ else:
+ # The response didn't contain audio data, exit gracefully
+ print("Could not stream audio")
+ sys.exit(-1)
+ except ProfileNotFound:
+ print("You need to install the AWS CLI and configure your profile")
+ print(
+ """
+ Linux: https://docs.aws.amazon.com/polly/latest/dg/setup-aws-cli.html
+ Windows: https://docs.aws.amazon.com/polly/latest/dg/install-voice-plugin2.html
+ """
+ )
sys.exit(-1)
def randomvoice(self):
diff --git a/TTS/engine_wrapper.py b/TTS/engine_wrapper.py
index 1f27521..762aa47 100644
--- a/TTS/engine_wrapper.py
+++ b/TTS/engine_wrapper.py
@@ -82,12 +82,16 @@ class TTSEngine:
r" *(((.|\n){0," + str(self.tts_module().max_chars) + "})(\.|.$))", text
)
]
-
- idy = None
+ offset = 0
for idy, text_cut in enumerate(split_text):
# print(f"{idx}-{idy}: {text_cut}\n")
- self.call_tts(f"{idx}-{idy}.part", text_cut)
- split_files.append(AudioFileClip(f"{self.path}/{idx}-{idy}.part.mp3"))
+ if not text_cut or text_cut.isspace():
+ offset += 1
+ continue
+
+ self.call_tts(f"{idx}-{idy - offset}.part", text_cut)
+ split_files.append(AudioFileClip(f"{self.path}/{idx}-{idy - offset}.part.mp3"))
+
CompositeAudioClip([concatenate_audioclips(split_files)]).write_audiofile(
f"{self.path}/{idx}.mp3", fps=44100, verbose=False, logger=None
)
diff --git a/TTS/streamlabs_polly.py b/TTS/streamlabs_polly.py
index b7365ab..75c4f49 100644
--- a/TTS/streamlabs_polly.py
+++ b/TTS/streamlabs_polly.py
@@ -37,8 +37,8 @@ class StreamlabsPolly:
voice = self.randomvoice()
else:
if not settings.config["settings"]["tts"]["streamlabs_polly_voice"]:
- return ValueError(
- f"Please set the config variable STREAMLABS_VOICE to a valid voice. options are: {voices}"
+ raise ValueError(
+ 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()
body = {"voice": voice, "text": text, "service": "polly"}
diff --git a/reddit/subreddit.py b/reddit/subreddit.py
index 31eb712..651e9a1 100644
--- a/reddit/subreddit.py
+++ b/reddit/subreddit.py
@@ -20,7 +20,7 @@ def get_subreddit_threads(
print_substep("Logging into Reddit.")
content = {}
- if settings.config["reddit"]["creds"]["2fa"] == True:
+ if settings.config["reddit"]["creds"]["2fa"]:
print("\nEnter your two-factor authentication code from your authenticator app.\n")
code = input("> ")
print()
@@ -29,7 +29,7 @@ def get_subreddit_threads(
else:
passkey = settings.config["reddit"]["creds"]["password"]
username = settings.config["reddit"]["creds"]["username"]
- if username.casefold().startswith("u/"):
+ if str(username).casefold().startswith("u/"):
username = username[2:]
reddit = praw.Reddit(
client_id=settings.config["reddit"]["creds"]["client_id"],
@@ -57,7 +57,7 @@ def get_subreddit_threads(
sub = settings.config["reddit"]["thread"]["subreddit"]
print_substep(f"Using subreddit: r/{sub} from TOML config")
subreddit_choice = sub
- if subreddit_choice.casefold().startswith("r/"): # removes the r/ from the input
+ if str(subreddit_choice).casefold().startswith("r/"): # removes the r/ from the input
subreddit_choice = subreddit_choice[2:]
subreddit = reddit.subreddit(
subreddit_choice
@@ -67,11 +67,10 @@ def get_subreddit_threads(
submission = reddit.submission(id=POST_ID)
elif (
settings.config["reddit"]["thread"]["post_id"]
- and len(settings.config["reddit"]["thread"]["post_id"].split("+")) == 1
+ and len(str(settings.config["reddit"]["thread"]["post_id"]).split("+")) == 1
):
submission = reddit.submission(id=settings.config["reddit"]["thread"]["post_id"])
else:
-
threads = subreddit.hot(limit=25)
submission = get_subreddit_undone(threads, subreddit)
submission = check_done(submission) # double-checking
@@ -107,6 +106,7 @@ def get_subreddit_threads(
):
if (
top_level_comment.author is not None
+ and sanitize_text(top_level_comment.body) is not None
): # if errors occur with this change to if not.
content["comments"].append(
{
diff --git a/requirements.txt b/requirements.txt
index 10ce9c3..0dc26df 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@ moviepy==1.0.3
praw==7.6.0
pytube==12.1.0
requests==2.28.1
-rich==12.4.4
+rich==12.5.1
toml==0.10.2
translators==5.3.1
pyppeteer==1.0.2
diff --git a/utils/subreddit.py b/utils/subreddit.py
index 48dceba..4eb0108 100644
--- a/utils/subreddit.py
+++ b/utils/subreddit.py
@@ -34,11 +34,16 @@ def get_subreddit_undone(submissions: list, subreddit):
if submission.stickied:
print_substep("This post was pinned by moderators. Skipping...")
continue
+ if submission.num_comments <= int(settings.config["reddit"]["thread"]["min_comments"]):
+ print_substep(
+ f'This post has under the specified minimum of comments ({settings.config["reddit"]["thread"]["min_comments"]}). Skipping...'
+ )
+ continue
return submission
print("all submissions have been done going by top submission order")
return get_subreddit_undone(
subreddit.top(time_filter="hour"), subreddit
- ) # all of the videos in hot have already been done
+ ) # all the videos in hot have already been done
def already_done(done_videos: list, submission) -> bool:
diff --git a/utils/voice.py b/utils/voice.py
index 4a77833..a0709fa 100644
--- a/utils/voice.py
+++ b/utils/voice.py
@@ -36,7 +36,7 @@ def sleep_until(time):
# Convert datetime to unix timestamp and adjust for locality
if isinstance(time, datetime):
- # If we're on Python 3 and the user specified a timezone, convert to UTC and get tje timestamp.
+ # If we're on Python 3 and the user specified a timezone, convert to UTC and get the timestamp.
if sys.version_info[0] >= 3 and time.tzinfo:
end = time.astimezone(timezone.utc).timestamp()
else:
diff --git a/video_creation/background.py b/video_creation/background.py
index 7ef4321..be0f46c 100644
--- a/video_creation/background.py
+++ b/video_creation/background.py
@@ -30,7 +30,7 @@ background_options = {
"https://www.youtube.com/watch?v=2X9QGY__0II",
"rocket_league.mp4",
"Orbital Gameplay",
- "top",
+ lambda t: ("center", 200 + t),
),
"minecraft": ( # Minecraft parkour
"https://www.youtube.com/watch?v=n_Dv4JMiwK8",
@@ -64,7 +64,7 @@ def get_start_and_end_times(video_length: int, length_of_clip: int) -> Tuple[int
def get_background_config():
"""Fetch the background/s configuration"""
try:
- choice = str(settings.config["settings"]["background_choice"]).casefold()
+ choice = str(settings.config["settings"]["background"]["background_choice"]).casefold()
except AttributeError:
print_substep("No background selected. Picking random background'")
choice = None
diff --git a/video_creation/final_video.py b/video_creation/final_video.py
index 6da3034..2dba251 100755
--- a/video_creation/final_video.py
+++ b/video_creation/final_video.py
@@ -5,8 +5,6 @@ import re
from os.path import exists
from typing import Tuple, Any
-import translators as ts
-
from moviepy.editor import (
VideoFileClip,
AudioFileClip,
@@ -44,6 +42,8 @@ def name_normalize(
lang = settings.config['reddit']['thread']['post_lang']
if lang:
+ import translators as ts
+
print_substep('Translating filename...')
translated_name = ts.google(name, to_language=lang)
return translated_name
@@ -196,38 +196,13 @@ def make_final_video(
verbose=False,
threads=multiprocessing.cpu_count(),
)
- if settings.config['settings']['background_audio']:
- print('[bold green] Merging background audio with video')
- if not exists('assets/backgrounds/background.mp3'):
- print_substep(
- 'Cannot find assets/backgrounds/background.mp3 audio file didn\'t so skipping.'
- )
- ffmpeg_extract_subclip(
- 'assets/temp/temp.mp4',
- 0,
- video_duration,
- targetname=f'results/{subreddit}/{filename}',
- )
- else:
- ffmpeg_merge_video_audio(
- 'assets/temp/temp.mp4',
- 'assets/backgrounds/background.mp3',
- 'assets/temp/temp_audio.mp4',
- )
- ffmpeg_extract_subclip( # check if this gets run
- 'assets/temp/temp_audio.mp4',
- 0,
- video_duration,
- targetname=f'results/{subreddit}/{filename}',
- )
- else:
- print('debug duck')
- ffmpeg_extract_subclip(
- 'assets/temp/temp.mp4',
- 0,
- video_duration,
- targetname=f'results/{subreddit}/{filename}',
- )
+ ffmpeg_extract_subclip(
+ "assets/temp/temp.mp4",
+ 0,
+ video_duration,
+ targetname=f'results/{subreddit}/{filename}',
+ )
+ save_data(subreddit, filename, title, idx, background_config[2])
print_step('Removing temporary files 🗑')
cleanups = cleanup()
print_substep(f'Removed {cleanups} temporary files 🗑')
diff --git a/video_creation/voices.py b/video_creation/voices.py
index 0098da0..95f0b2b 100644
--- a/video_creation/voices.py
+++ b/video_creation/voices.py
@@ -29,7 +29,7 @@ def save_text_to_mp3(
"""
voice = settings.config['settings']['tts']['choice']
- if voice.casefold() not in map(lambda _: _.casefold(), TTSProviders):
+ if str(voice).casefold() not in map(lambda _: _.casefold(), TTSProviders):
while True:
print_step('Please choose one of the following TTS providers: ')
print_table(TTSProviders)