1 parent
9ba4500c27
commit
dbf68477a6
10 files changed
+251
-133
No files matched your search
@@ -11,19 +11,20 @@ from video_creation.final_video import make_final_video
|
||||
from video_creation.screenshot_downloader import download_screenshots_of_reddit_posts
|
||||
from video_creation.voices import save_text_to_mp3
|
||||
|
||||
banner = '''
|
||||
banner = """
|
||||
██████╗ ███████╗██████╗ ██████╗ ██╗████████╗ ██╗ ██╗██╗██████╗ ███████╗ ██████╗ ███╗ ███╗ █████╗ ██╗ ██╗███████╗██████╗
|
||||
██╔══██╗██╔════╝██╔══██╗██╔══██╗██║╚══██╔══╝ ██║ ██║██║██╔══██╗██╔════╝██╔═══██╗ ████╗ ████║██╔══██╗██║ ██╔╝██╔════╝██╔══██╗
|
||||
██████╔╝█████╗ ██║ ██║██║ ██║██║ ██║ ██║ ██║██║██║ ██║█████╗ ██║ ██║ ██╔████╔██║███████║█████╔╝ █████╗ ██████╔╝
|
||||
██╔══██╗██╔══╝ ██║ ██║██║ ██║██║ ██║ ╚██╗ ██╔╝██║██║ ██║██╔══╝ ██║ ██║ ██║╚██╔╝██║██╔══██║██╔═██╗ ██╔══╝ ██╔══██╗
|
||||
██║ ██║███████╗██████╔╝██████╔╝██║ ██║ ╚████╔╝ ██║██████╔╝███████╗╚██████╔╝ ██║ ╚═╝ ██║██║ ██║██║ ██╗███████╗██║ ██║
|
||||
╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
|
||||
'''
|
||||
"""
|
||||
print(banner)
|
||||
load_dotenv()
|
||||
# base code by elebumm
|
||||
print_markdown(
|
||||
"### Thanks for using this tool! 😊 Feel free to contribute to this project on GitHub! (JasonLovesDoggo/RedditVideoMakerBot). If you have any questions, feel free to reach out to me on Twitter @JasonLovesDoggo or submit a GitHub issue.")
|
||||
"### Thanks for using this tool! 😊 Feel free to contribute to this project on GitHub! (JasonLovesDoggo/RedditVideoMakerBot). If you have any questions, feel free to reach out to me on Twitter @JasonLovesDoggo or submit a GitHub issue."
|
||||
)
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
@@ -47,15 +48,16 @@ def run_many(times):
|
||||
for x in range(times):
|
||||
x = x + 1
|
||||
print_step(
|
||||
f'on the {x}{("st" if x == 1 else ("nd" if x == 2 else ("rd" if x == 3 else "th")))} iteration of {times}') # correct 1st 2nd 3rd 4th 5th....
|
||||
f'on the {x}{("st" if x == 1 else ("nd" if x == 2 else ("rd" if x == 3 else "th")))} iteration of {times}'
|
||||
) # correct 1st 2nd 3rd 4th 5th....
|
||||
main()
|
||||
Popen('cls' if name == 'nt' else 'clear', shell=True).wait()
|
||||
Popen("cls" if name == "nt" else "clear", shell=True).wait()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
if getenv('TIMES_TO_RUN'):
|
||||
run_many(int(getenv('TIMES_TO_RUN')))
|
||||
if getenv("TIMES_TO_RUN"):
|
||||
run_many(int(getenv("TIMES_TO_RUN")))
|
||||
else:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
|
||||
+37
-18
@@ -6,11 +6,11 @@ import praw
|
||||
from utils.console import print_step, print_substep
|
||||
from utils.videos import check_done
|
||||
|
||||
TEXT_WHITELIST = set('abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890')
|
||||
TEXT_WHITELIST = set("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890")
|
||||
|
||||
|
||||
def textify(text):
|
||||
return ''.join(filter(TEXT_WHITELIST.__contains__, text))
|
||||
return "".join(filter(TEXT_WHITELIST.__contains__, text))
|
||||
|
||||
|
||||
def get_subreddit_threads():
|
||||
@@ -22,29 +22,40 @@ def get_subreddit_threads():
|
||||
|
||||
content = {}
|
||||
if getenv("REDDIT_2FA").casefold() == "yes":
|
||||
print("\nEnter your two-factor authentication code from your authenticator app.\n")
|
||||
print(
|
||||
"\nEnter your two-factor authentication code from your authenticator app.\n"
|
||||
)
|
||||
code = input("> ")
|
||||
print()
|
||||
pw = getenv("REDDIT_PASSWORD")
|
||||
passkey = f"{pw}:{code}"
|
||||
else:
|
||||
passkey = getenv("REDDIT_PASSWORD")
|
||||
reddit = praw.Reddit(client_id=getenv("REDDIT_CLIENT_ID"), client_secret=getenv("REDDIT_CLIENT_SECRET"),
|
||||
user_agent="Accessing Reddit threads", username=getenv("REDDIT_USERNAME"),
|
||||
passkey=passkey, check_for_async=False,)
|
||||
reddit = praw.Reddit(
|
||||
client_id=getenv("REDDIT_CLIENT_ID"),
|
||||
client_secret=getenv("REDDIT_CLIENT_SECRET"),
|
||||
user_agent="Accessing Reddit threads",
|
||||
username=getenv("REDDIT_USERNAME"),
|
||||
passkey=passkey,
|
||||
check_for_async=False,
|
||||
)
|
||||
"""
|
||||
Ask user for subreddit input
|
||||
"""
|
||||
if not getenv("SUBREDDIT"):
|
||||
subreddit = reddit.subreddit(
|
||||
input("What subreddit would you like to pull from? ")) # if the env isnt set, ask user
|
||||
input("What subreddit would you like to pull from? ")
|
||||
) # if the env isnt set, ask user
|
||||
else:
|
||||
print_substep(f"Using subreddit: r/{getenv('SUBREDDIT')} from environment variable config")
|
||||
print_substep(
|
||||
f"Using subreddit: r/{getenv('SUBREDDIT')} from environment variable config"
|
||||
)
|
||||
subreddit = reddit.subreddit(
|
||||
getenv("SUBREDDIT")) # Allows you to specify in .env. Done for automation purposes.
|
||||
getenv("SUBREDDIT")
|
||||
) # Allows you to specify in .env. Done for automation purposes.
|
||||
|
||||
if getenv('POST_ID'):
|
||||
submission = reddit.submission(id=getenv('POST_ID'))
|
||||
if getenv("POST_ID"):
|
||||
submission = reddit.submission(id=getenv("POST_ID"))
|
||||
else:
|
||||
threads = subreddit.hot(limit=25)
|
||||
submission = list(threads)[random.randrange(0, 25)]
|
||||
@@ -55,11 +66,15 @@ def get_subreddit_threads():
|
||||
ratio = submission.upvote_ratio * 100
|
||||
num_comments = submission.num_comments
|
||||
|
||||
print_substep(f"Video will be: {submission.title} :thumbsup:", style='bold green')
|
||||
print_substep(f"Thread has " + str(upvotes) + " upvotes", style='bold blue')
|
||||
print_substep(f"Thread has a upvote ratio of " + str(ratio) + "%", style='bold blue')
|
||||
print_substep(f"Thread has " + str(num_comments) + " comments", style='bold blue')
|
||||
environ["VIDEO_TITLE"] = str(textify(submission.title)) # todo use global instend of env vars
|
||||
print_substep(f"Video will be: {submission.title} :thumbsup:", style="bold green")
|
||||
print_substep(f"Thread has " + str(upvotes) + " upvotes", style="bold blue")
|
||||
print_substep(
|
||||
f"Thread has a upvote ratio of " + str(ratio) + "%", style="bold blue"
|
||||
)
|
||||
print_substep(f"Thread has " + str(num_comments) + " comments", style="bold blue")
|
||||
environ["VIDEO_TITLE"] = str(
|
||||
textify(submission.title)
|
||||
) # todo use global instend of env vars
|
||||
environ["VIDEO_ID"] = str(textify(submission.id))
|
||||
try:
|
||||
|
||||
@@ -71,8 +86,12 @@ def get_subreddit_threads():
|
||||
if not top_level_comment.stickied:
|
||||
if len(top_level_comment.body) <= int(environ["MAX_COMMENT_LENGTH"]):
|
||||
content["comments"].append(
|
||||
{"comment_body": top_level_comment.body, "comment_url": top_level_comment.permalink,
|
||||
"comment_id": top_level_comment.id, })
|
||||
{
|
||||
"comment_body": top_level_comment.body,
|
||||
"comment_url": top_level_comment.permalink,
|
||||
"comment_id": top_level_comment.id,
|
||||
}
|
||||
)
|
||||
except AttributeError as e:
|
||||
pass
|
||||
print_substep("Received subreddit threads Successfully.", style="bold green")
|
||||
|
||||
+8
-6
@@ -3,20 +3,22 @@ from os.path import exists
|
||||
|
||||
|
||||
def cleanup() -> int:
|
||||
if exists('./assets/temp'):
|
||||
if exists("./assets/temp"):
|
||||
count = 0
|
||||
files = [f for f in os.listdir('.') if f.endswith('.mp4') and 'temp' in f.lower()]
|
||||
files = [
|
||||
f for f in os.listdir(".") if f.endswith(".mp4") and "temp" in f.lower()
|
||||
]
|
||||
count += len(files)
|
||||
for f in files:
|
||||
os.remove(f)
|
||||
try:
|
||||
for file in os.listdir('./assets/temp/mp4'):
|
||||
for file in os.listdir("./assets/temp/mp4"):
|
||||
count += 1
|
||||
os.remove('./assets/temp/mp4/' + file)
|
||||
os.remove("./assets/temp/mp4/" + file)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
for file in os.listdir('./assets/temp/mp3'):
|
||||
for file in os.listdir("./assets/temp/mp3"):
|
||||
count += 1
|
||||
os.remove('./assets/temp/mp3/' + file)
|
||||
os.remove("./assets/temp/mp3/" + file)
|
||||
return count
|
||||
return 0
|
||||
+10
-7
@@ -4,17 +4,20 @@ from os import getenv
|
||||
from utils.console import print_step
|
||||
|
||||
|
||||
def check_done(redditobj): # don't set this to be run anyplace that isn't subreddit.py bc of inspect stack
|
||||
def check_done(
|
||||
redditobj,
|
||||
): # don't set this to be run anyplace that isn't subreddit.py bc of inspect stack
|
||||
"""params:
|
||||
reddit_object: The Reddit Object you received in askreddit.py"""
|
||||
with open('./video_creation/data/videos.json', 'r') as done_vids_raw:
|
||||
reddit_object: The Reddit Object you received in askreddit.py"""
|
||||
with open("./video_creation/data/videos.json", "r") as done_vids_raw:
|
||||
done_videos = json.load(done_vids_raw)
|
||||
for video in done_videos:
|
||||
if video['id'] == str(redditobj):
|
||||
if getenv('POST_ID'):
|
||||
if video["id"] == str(redditobj):
|
||||
if getenv("POST_ID"):
|
||||
print_step(
|
||||
'You already have done this video but since it was declared specifically in the .env file the program will continue')
|
||||
"You already have done this video but since it was declared specifically in the .env file the program will continue"
|
||||
)
|
||||
return redditobj
|
||||
print_step('Getting new post as the current one has already been done')
|
||||
print_step("Getting new post as the current one has already been done")
|
||||
return None
|
||||
return redditobj
|
||||
+1
-1
@@ -10,7 +10,7 @@ def sanitize_text(text):
|
||||
"""
|
||||
|
||||
# remove any urls from the text
|
||||
regex_urls = r'((http|https)\:\/\/)?[a-zA-Z0-9\.\/\?\:@\-_=#]+\.([a-zA-Z]){2,6}([a-zA-Z0-9\.\&\/\?\:@\-_=#])*'
|
||||
regex_urls = r"((http|https)\:\/\/)?[a-zA-Z0-9\.\/\?\:@\-_=#]+\.([a-zA-Z]){2,6}([a-zA-Z0-9\.\&\/\?\:@\-_=#])*"
|
||||
|
||||
result = re.sub(regex_urls, " ", text)
|
||||
|
||||
|
||||
@@ -5,55 +5,55 @@ import os
|
||||
import random
|
||||
import requests
|
||||
from moviepy.editor import AudioFileClip, concatenate_audioclips, CompositeAudioClip
|
||||
#from profanity_filter import ProfanityFilter
|
||||
#pf = ProfanityFilter()
|
||||
|
||||
# from profanity_filter import ProfanityFilter
|
||||
# pf = ProfanityFilter()
|
||||
# Code by @JasonLovesDoggo
|
||||
# https://twitter.com/scanlime/status/1512598559769702406
|
||||
nonhuman = [ # DISNEY VOICES
|
||||
'en_us_ghostface', # Ghost Face
|
||||
'en_us_chewbacca', # Chewbacca
|
||||
'en_us_c3po', # C3PO
|
||||
'en_us_stitch', # Stitch
|
||||
'en_us_stormtrooper', # Stormtrooper
|
||||
'en_us_rocket', # Rocket
|
||||
|
||||
"en_us_ghostface", # Ghost Face
|
||||
"en_us_chewbacca", # Chewbacca
|
||||
"en_us_c3po", # C3PO
|
||||
"en_us_stitch", # Stitch
|
||||
"en_us_stormtrooper", # Stormtrooper
|
||||
"en_us_rocket", # Rocket
|
||||
# ENGLISH VOICES
|
||||
]
|
||||
human = ['en_au_001', # English AU - Female
|
||||
'en_au_002', # English AU - Male
|
||||
'en_uk_001', # English UK - Male 1
|
||||
'en_uk_003', # English UK - Male 2
|
||||
'en_us_001', # English US - Female (Int. 1)
|
||||
'en_us_002', # English US - Female (Int. 2)
|
||||
'en_us_006', # English US - Male 1
|
||||
'en_us_007', # English US - Male 2
|
||||
'en_us_009', # English US - Male 3
|
||||
'en_us_010']
|
||||
human = [
|
||||
"en_au_001", # English AU - Female
|
||||
"en_au_002", # English AU - Male
|
||||
"en_uk_001", # English UK - Male 1
|
||||
"en_uk_003", # English UK - Male 2
|
||||
"en_us_001", # English US - Female (Int. 1)
|
||||
"en_us_002", # English US - Female (Int. 2)
|
||||
"en_us_006", # English US - Male 1
|
||||
"en_us_007", # English US - Male 2
|
||||
"en_us_009", # English US - Male 3
|
||||
"en_us_010",
|
||||
]
|
||||
voices = nonhuman + human
|
||||
|
||||
noneng = [
|
||||
'fr_001', # French - Male 1
|
||||
'fr_002', # French - Male 2
|
||||
'de_001', # German - Female
|
||||
'de_002', # German - Male
|
||||
'es_002', # Spanish - Male
|
||||
|
||||
"fr_001", # French - Male 1
|
||||
"fr_002", # French - Male 2
|
||||
"de_001", # German - Female
|
||||
"de_002", # German - Male
|
||||
"es_002", # Spanish - Male
|
||||
# AMERICA VOICES
|
||||
'es_mx_002', # Spanish MX - Male
|
||||
'br_001', # Portuguese BR - Female 1
|
||||
'br_003', # Portuguese BR - Female 2
|
||||
'br_004', # Portuguese BR - Female 3
|
||||
'br_005', # Portuguese BR - Male
|
||||
|
||||
"es_mx_002", # Spanish MX - Male
|
||||
"br_001", # Portuguese BR - Female 1
|
||||
"br_003", # Portuguese BR - Female 2
|
||||
"br_004", # Portuguese BR - Female 3
|
||||
"br_005", # Portuguese BR - Male
|
||||
# ASIA VOICES
|
||||
'id_001', # Indonesian - Female
|
||||
'jp_001', # Japanese - Female 1
|
||||
'jp_003', # Japanese - Female 2
|
||||
'jp_005', # Japanese - Female 3
|
||||
'jp_006', # Japanese - Male
|
||||
'kr_002', # Korean - Male 1
|
||||
'kr_003', # Korean - Female
|
||||
'kr_004', # Korean - Male 2
|
||||
"id_001", # Indonesian - Female
|
||||
"jp_001", # Japanese - Female 1
|
||||
"jp_003", # Japanese - Female 2
|
||||
"jp_005", # Japanese - Female 3
|
||||
"jp_006", # Japanese - Male
|
||||
"kr_002", # Korean - Male 1
|
||||
"kr_003", # Korean - Female
|
||||
"kr_004", # Korean - Male 2
|
||||
]
|
||||
|
||||
|
||||
@@ -63,22 +63,36 @@ noneng = [
|
||||
|
||||
class TTTTSWrapper: # TikTok Text-to-Speech Wrapper
|
||||
def __init__(self):
|
||||
self.URI_BASE = 'https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/?text_speaker='
|
||||
self.URI_BASE = "https://api16-normal-useast5.us.tiktokv.com/media/api/text/speech/invoke/?text_speaker="
|
||||
|
||||
def tts(self, req_text: str = "TikTok Text To Speech", filename: str = 'title.mp3', random_speaker: bool = False, censer=False):
|
||||
def tts(
|
||||
self,
|
||||
req_text: str = "TikTok Text To Speech",
|
||||
filename: str = "title.mp3",
|
||||
random_speaker: bool = False,
|
||||
censer=False,
|
||||
):
|
||||
req_text = req_text.replace("+", "plus").replace(" ", "+").replace("&", "and")
|
||||
if censer:
|
||||
#req_text = pf.censor(req_text)
|
||||
# req_text = pf.censor(req_text)
|
||||
pass
|
||||
voice = self.randomvoice() if random_speaker else (os.getenv('VOICE') or random.choice(human))
|
||||
voice = (
|
||||
self.randomvoice()
|
||||
if random_speaker
|
||||
else (os.getenv("VOICE") or random.choice(human))
|
||||
)
|
||||
|
||||
chunks = [m.group().strip() for m in re.finditer(r' *((.{0,200})(\.|.$))', req_text)]
|
||||
chunks = [
|
||||
m.group().strip() for m in re.finditer(r" *((.{0,200})(\.|.$))", req_text)
|
||||
]
|
||||
|
||||
audio_clips = []
|
||||
|
||||
chunkId = 0
|
||||
for chunk in chunks:
|
||||
r = requests.post(f"{self.URI_BASE}{voice}&req_text={chunk}&speaker_map_type=0")
|
||||
r = requests.post(
|
||||
f"{self.URI_BASE}{voice}&req_text={chunk}&speaker_map_type=0"
|
||||
)
|
||||
vstr = [r.json()["data"]["v_str"]][0]
|
||||
b64d = base64.b64decode(vstr)
|
||||
|
||||
|
||||
@@ -14,34 +14,47 @@ def get_start_and_end_times(video_length, length_of_clip):
|
||||
|
||||
|
||||
def download_background():
|
||||
"""Downloads the backgrounds/s video from youtube.
|
||||
|
||||
"""
|
||||
"""Downloads the backgrounds/s video from youtube."""
|
||||
Path("./assets/backgrounds/").mkdir(parents=True, exist_ok=True)
|
||||
background_options = [ # uri , filename , credit
|
||||
("https://www.youtube.com/watch?v=n_Dv4JMiwK8", "parkour.mp4", 'bbswitzer'),
|
||||
("https://www.youtube.com/watch?v=2X9QGY__0II", "rocket_league.mp4", 'Orbital Gameplay'), ]
|
||||
("https://www.youtube.com/watch?v=n_Dv4JMiwK8", "parkour.mp4", "bbswitzer"),
|
||||
(
|
||||
"https://www.youtube.com/watch?v=2X9QGY__0II",
|
||||
"rocket_league.mp4",
|
||||
"Orbital Gameplay",
|
||||
),
|
||||
]
|
||||
# note: make sure the file name doesn't include a - in it
|
||||
if len(listdir('./assets/backgrounds')) != len(
|
||||
background_options): # if there are any background videos not installed
|
||||
print_step("We need to download the backgnrounds videos. they are fairly large but it's only done once. 😎")
|
||||
if len(listdir("./assets/backgrounds")) != len(
|
||||
background_options
|
||||
): # if there are any background videos not installed
|
||||
print_step(
|
||||
"We need to download the backgnrounds videos. they are fairly large but it's only done once. 😎"
|
||||
)
|
||||
print_substep("Downloading the backgrounds videos... please be patient 🙏 ")
|
||||
for uri, filename, credit in background_options:
|
||||
print_substep(f"Downloading {filename} from {uri}")
|
||||
YouTube(uri).streams.filter(res="1080p").first().download("assets/backgrounds",
|
||||
filename=f"{credit}-{filename}")
|
||||
YouTube(uri).streams.filter(res="1080p").first().download(
|
||||
"assets/backgrounds", filename=f"{credit}-{filename}"
|
||||
)
|
||||
|
||||
print_substep("Background videos downloaded successfully! 🎉", style="bold green")
|
||||
print_substep(
|
||||
"Background videos downloaded successfully! 🎉", style="bold green"
|
||||
)
|
||||
|
||||
|
||||
def chop_background_video(video_length):
|
||||
print_step("Finding a spot in the backgrounds video to chop...✂️")
|
||||
choice = random.choice(listdir('assets/backgrounds'))
|
||||
environ["background_credit"] = choice.split('-')[0]
|
||||
choice = random.choice(listdir("assets/backgrounds"))
|
||||
environ["background_credit"] = choice.split("-")[0]
|
||||
|
||||
background = VideoFileClip(f"assets/backgrounds/{choice}")
|
||||
|
||||
start_time, end_time = get_start_and_end_times(video_length, background.duration)
|
||||
ffmpeg_extract_subclip(f'assets/backgrounds/{choice}', start_time, end_time,
|
||||
targetname="assets/temp/background.mp4", )
|
||||
ffmpeg_extract_subclip(
|
||||
f"assets/backgrounds/{choice}",
|
||||
start_time,
|
||||
end_time,
|
||||
targetname="assets/temp/background.mp4",
|
||||
)
|
||||
print_substep("Background video chopped successfully! 🎉", style="bold green")
|
||||
@@ -3,8 +3,15 @@ import os
|
||||
import time
|
||||
from os.path import exists
|
||||
|
||||
from moviepy.editor import VideoFileClip, AudioFileClip, ImageClip, concatenate_videoclips, concatenate_audioclips, \
|
||||
CompositeAudioClip, CompositeVideoClip
|
||||
from moviepy.editor import (
|
||||
VideoFileClip,
|
||||
AudioFileClip,
|
||||
ImageClip,
|
||||
concatenate_videoclips,
|
||||
concatenate_audioclips,
|
||||
CompositeAudioClip,
|
||||
CompositeVideoClip,
|
||||
)
|
||||
from moviepy.video.io import ffmpeg_tools
|
||||
|
||||
from reddit import subreddit
|
||||
@@ -18,10 +25,13 @@ def make_final_video(number_of_clips, length):
|
||||
print_step("Creating the final video 🎥")
|
||||
VideoFileClip.reW = lambda clip: clip.resize(width=W)
|
||||
VideoFileClip.reH = lambda clip: clip.resize(width=H)
|
||||
opacity = os.getenv('OPACITY')
|
||||
opacity = os.getenv("OPACITY")
|
||||
background_clip = (
|
||||
VideoFileClip("assets/temp/background.mp4").without_audio().resize(height=H).crop(x1=1166.6, y1=0, x2=2246.6,
|
||||
y2=1920))
|
||||
VideoFileClip("assets/temp/background.mp4")
|
||||
.without_audio()
|
||||
.resize(height=H)
|
||||
.crop(x1=1166.6, y1=0, x2=2246.6, y2=1920)
|
||||
)
|
||||
# Gather all audio clips
|
||||
audio_clips = []
|
||||
for i in range(0, number_of_clips):
|
||||
@@ -33,13 +43,41 @@ def make_final_video(number_of_clips, length):
|
||||
# Gather all images
|
||||
image_clips = []
|
||||
for i in range(0, number_of_clips):
|
||||
image_clips.append(
|
||||
ImageClip(f"assets/temp/png/comment_{i}.png").set_duration(audio_clips[i + 1].duration).set_position(
|
||||
"center").resize(width=W - 100).set_opacity(float(opacity)), )
|
||||
image_clips.insert(0, ImageClip(f"assets/temp/png/title.png").set_duration(audio_clips[0].duration).set_position(
|
||||
"center").resize(width=W - 100).set_opacity(float(opacity)),
|
||||
)
|
||||
image_concat = concatenate_videoclips(image_clips).set_position(("center", "center"))
|
||||
if opacity is None or opacity >= 1: # opacity not set or is set to one OR MORE
|
||||
image_clips.append(
|
||||
ImageClip(f"assets/temp/png/comment_{i}.png")
|
||||
.set_duration(audio_clips[i + 1].duration)
|
||||
.set_position("center")
|
||||
.resize(width=W - 100),
|
||||
)
|
||||
else:
|
||||
image_clips.append(
|
||||
ImageClip(f"assets/temp/png/comment_{i}.png")
|
||||
.set_duration(audio_clips[i + 1].duration)
|
||||
.set_position("center")
|
||||
.resize(width=W - 100)
|
||||
.set_opacity(float(opacity)),
|
||||
)
|
||||
if opacity is None or opacity >= 1: # opacity not set or is set to one OR MORE
|
||||
image_clips.insert(
|
||||
0,
|
||||
ImageClip(f"assets/temp/png/title.png")
|
||||
.set_duration(audio_clips[0].duration)
|
||||
.set_position("center")
|
||||
.resize(width=W - 100),
|
||||
)
|
||||
else:
|
||||
image_clips.insert(
|
||||
0,
|
||||
ImageClip(f"assets/temp/png/title.png")
|
||||
.set_duration(audio_clips[0].duration)
|
||||
.set_position("center")
|
||||
.resize(width=W - 100)
|
||||
.set_opacity(float(opacity)),
|
||||
)
|
||||
image_concat = concatenate_videoclips(image_clips).set_position(
|
||||
("center", "center")
|
||||
)
|
||||
image_concat.audio = audio_composite
|
||||
final = CompositeVideoClip([background_clip, image_concat])
|
||||
|
||||
@@ -50,27 +88,35 @@ def make_final_video(number_of_clips, length):
|
||||
else:
|
||||
return title[0:30] + "..."
|
||||
|
||||
filename = f'{get_video_title()}.mp4'
|
||||
filename = f"{get_video_title()}.mp4"
|
||||
|
||||
def save_data():
|
||||
with open('./video_creation/data/videos.json', 'r+') as raw_vids:
|
||||
with open("./video_creation/data/videos.json", "r+") as raw_vids:
|
||||
done_vids = json.load(raw_vids)
|
||||
if str(subreddit.submission.id) in [video['id'] for video in done_vids]:
|
||||
if str(subreddit.submission.id) in [video["id"] for video in done_vids]:
|
||||
return # video already done but was specified to continue anyway in the .env file
|
||||
payload = {"id": str(os.getenv("VIDEO_ID")), 'time': str(int(time.time())),
|
||||
"background_credit": str(os.getenv('background_credit')),
|
||||
"reddit_title": str(os.getenv('VIDEO_TITLE')), "filename": filename}
|
||||
payload = {
|
||||
"id": str(os.getenv("VIDEO_ID")),
|
||||
"time": str(int(time.time())),
|
||||
"background_credit": str(os.getenv("background_credit")),
|
||||
"reddit_title": str(os.getenv("VIDEO_TITLE")),
|
||||
"filename": filename,
|
||||
}
|
||||
done_vids.append(payload)
|
||||
raw_vids.seek(0)
|
||||
json.dump(done_vids, raw_vids, ensure_ascii=False, indent=4)
|
||||
|
||||
save_data()
|
||||
if not exists('./results'):
|
||||
print_substep('the results folder didn\'t exist so I made it')
|
||||
if not exists("./results"):
|
||||
print_substep("the results folder didn't exist so I made it")
|
||||
os.mkdir("./results")
|
||||
|
||||
final.write_videofile("assets/temp/temp.mp4", fps=30, audio_codec="aac", audio_bitrate="192k")
|
||||
ffmpeg_tools.ffmpeg_extract_subclip("assets/temp/temp.mp4", 0, length, targetname=f"results/{filename}")
|
||||
final.write_videofile(
|
||||
"assets/temp/temp.mp4", fps=30, audio_codec="aac", audio_bitrate="192k"
|
||||
)
|
||||
ffmpeg_tools.ffmpeg_extract_subclip(
|
||||
"assets/temp/temp.mp4", 0, length, targetname=f"results/{filename}"
|
||||
)
|
||||
# os.remove("assets/temp/temp.mp4")
|
||||
|
||||
print_step("Removing temporary files 🗑")
|
||||
@@ -78,4 +124,6 @@ def make_final_video(number_of_clips, length):
|
||||
print_substep(f"Removed {cleanups} temporary files 🗑")
|
||||
print_substep(f"See result in the results folder!")
|
||||
|
||||
print_step(f"Reddit title: {os.getenv('VIDEO_TITLE')} \n Background Credit: {os.getenv('background_credit')}")
|
||||
print_step(
|
||||
f"Reddit title: {os.getenv('VIDEO_TITLE')} \n Background Credit: {os.getenv('background_credit')}"
|
||||
)
|
||||
@@ -28,9 +28,9 @@ def download_screenshots_of_reddit_posts(reddit_object, screenshot_num):
|
||||
context = browser.new_context()
|
||||
|
||||
if getenv("THEME").upper() == "DARK":
|
||||
cookie_file = open('./video_creation/data/cookie-dark-mode.json')
|
||||
cookie_file = open("./video_creation/data/cookie-dark-mode.json")
|
||||
else:
|
||||
cookie_file = open('./video_creation/data/cookie-light-mode.json')
|
||||
cookie_file = open("./video_creation/data/cookie-light-mode.json")
|
||||
cookies = json.load(cookie_file)
|
||||
context.add_cookies(cookies)
|
||||
# Get the thread screenshot
|
||||
@@ -43,14 +43,19 @@ def download_screenshots_of_reddit_posts(reddit_object, screenshot_num):
|
||||
if getenv("ALLOW_NSFW").casefold() == "false":
|
||||
print_substep("NSFW Post Detected. Skipping...")
|
||||
from main import main
|
||||
|
||||
main()
|
||||
|
||||
print_substep("Post is NSFW. You are spicy... :fire:")
|
||||
page.locator('[data-testid="content-gate"] button').click()
|
||||
|
||||
page.locator('[data-test-id="post-content"]').screenshot(path="assets/temp/png/title.png")
|
||||
page.locator('[data-test-id="post-content"]').screenshot(
|
||||
path="assets/temp/png/title.png"
|
||||
)
|
||||
|
||||
for idx, comment in track(enumerate(reddit_object["comments"]), "Downloading screenshots..."):
|
||||
for idx, comment in track(
|
||||
enumerate(reddit_object["comments"]), "Downloading screenshots..."
|
||||
):
|
||||
|
||||
# Stop if we have reached the screenshot_num
|
||||
if idx >= screenshot_num:
|
||||
@@ -60,5 +65,7 @@ def download_screenshots_of_reddit_posts(reddit_object, screenshot_num):
|
||||
page.locator('[data-testid="content-gate"] button').click()
|
||||
|
||||
page.goto(f'https://reddit.com{comment["comment_url"]}')
|
||||
page.locator(f"#t1_{comment['comment_id']}").screenshot(path=f"assets/temp/png/comment_{idx}.png")
|
||||
page.locator(f"#t1_{comment['comment_id']}").screenshot(
|
||||
path=f"assets/temp/png/comment_{idx}.png"
|
||||
)
|
||||
print_substep("Screenshots downloaded Successfully.", style="bold green")
|
||||
@@ -25,7 +25,11 @@ def save_text_to_mp3(reddit_obj):
|
||||
Path("assets/temp/mp3").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
ttttsw = TTTTSWrapper() # tiktok text to speech wrapper
|
||||
ttttsw.tts(sanitize_text(reddit_obj["thread_title"]), filename=f"assets/temp/mp3/title.mp3", random_speaker=False)
|
||||
ttttsw.tts(
|
||||
sanitize_text(reddit_obj["thread_title"]),
|
||||
filename=f"assets/temp/mp3/title.mp3",
|
||||
random_speaker=False,
|
||||
)
|
||||
try:
|
||||
length += MP3(f"assets/temp/mp3/title.mp3").info.length
|
||||
except HeaderNotFoundError: # note to self AudioFileClip
|
||||
@@ -36,7 +40,11 @@ def save_text_to_mp3(reddit_obj):
|
||||
if length > VIDEO_LENGTH:
|
||||
break
|
||||
|
||||
ttttsw.tts(sanitize_text(comment["comment_body"]), filename=f"assets/temp/mp3/{com}.mp3", random_speaker=False)
|
||||
ttttsw.tts(
|
||||
sanitize_text(comment["comment_body"]),
|
||||
filename=f"assets/temp/mp3/{com}.mp3",
|
||||
random_speaker=False,
|
||||
)
|
||||
try:
|
||||
length += MP3(f"assets/temp/mp3/{com}.mp3").info.length
|
||||
com += 1
|
||||
@@ -45,9 +53,11 @@ def save_text_to_mp3(reddit_obj):
|
||||
length += sox.file_info.duration(f"assets/temp/mp3/{com}.mp3")
|
||||
com += 1
|
||||
except (OSError, IOError):
|
||||
print('would have removed'
|
||||
f"assets/temp/mp3/{com}.mp3"
|
||||
f"assets/temp/png/comment_{com}.png")
|
||||
print(
|
||||
"would have removed"
|
||||
f"assets/temp/mp3/{com}.mp3"
|
||||
f"assets/temp/png/comment_{com}.png"
|
||||
)
|
||||
# remove(f"assets/temp/mp3/{com}.mp3")
|
||||
# remove(f"assets/temp/png/comment_{com}.png")# todo might cause odd un-syncing
|
||||
|
||||
|
||||
Reference in new issue
Block a user