using smth with os.remove and I don't want to accidentally delete anything important
This commit is contained in:
1 parent
5b3989611f
commit
51484ca401
10 files changed
+156
-87
No files matched your search
+3
-1
@@ -1,4 +1,6 @@
|
||||
REDDIT_CLIENT_ID=""
|
||||
REDDIT_CLIENT_SECRET=""
|
||||
REDDIT_USERNAME=""
|
||||
REDDIT_PASSWORD=""
|
||||
REDDIT_PASSWORD=""
|
||||
SUBREDDIT="AskReddit"
|
||||
ALLOW_NSFW="False"
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
assets/
|
||||
.env
|
||||
reddit-bot-351418-5560ebc49cac.json
|
||||
reddit-bot-351418-5560ebc49cac.json
|
||||
/.idea
|
||||
@@ -1,6 +1,6 @@
|
||||
from utils.console import print_markdown
|
||||
import time
|
||||
from reddit.askreddit import get_askreddit_threads
|
||||
from reddit.subreddit import get_subreddit_threads
|
||||
from video_creation.background import download_background, chop_background_video
|
||||
from video_creation.voices import save_text_to_mp3
|
||||
from video_creation.screenshot_downloader import download_screenshots_of_reddit_posts
|
||||
@@ -10,13 +10,17 @@ print_markdown(
|
||||
"### Thanks for using this tool! 😊 [Feel free to contribute to this project on GitHub!](https://lewismenelaws.com). If you have any questions, feel free to reach out to me on Twitter or submit a GitHub issue."
|
||||
)
|
||||
|
||||
time.sleep(3)
|
||||
time.sleep(2)
|
||||
|
||||
def main():
|
||||
reddit_object = get_subreddit_threads()
|
||||
|
||||
length, number_of_comments = save_text_to_mp3(reddit_object)
|
||||
download_screenshots_of_reddit_posts(reddit_object, number_of_comments)
|
||||
download_background()
|
||||
chop_background_video(length)
|
||||
final_video = make_final_video(number_of_comments)
|
||||
|
||||
|
||||
reddit_object = get_askreddit_threads()
|
||||
|
||||
length, number_of_comments = save_text_to_mp3(reddit_object)
|
||||
download_screenshots_of_reddit_posts(reddit_object, number_of_comments)
|
||||
download_background()
|
||||
chop_background_video(length)
|
||||
final_video = make_final_video(number_of_comments)
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,61 @@
|
||||
import re
|
||||
|
||||
from utils.console import print_step, print_substep
|
||||
import praw
|
||||
import random
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
|
||||
|
||||
def ascifi(text):
|
||||
regrex_pattern = re.compile(pattern="["
|
||||
u"\U0001F600-\U0001F64F" # emoticons
|
||||
u"\U0001F300-\U0001F5FF" # symbols & pictographs
|
||||
u"\U0001F680-\U0001F6FF" # transport & map symbols
|
||||
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||||
"]+", flags=re.UNICODE)
|
||||
return regrex_pattern.sub(r'', text)
|
||||
|
||||
|
||||
def get_subreddit_threads():
|
||||
"""
|
||||
Returns a list of threads from the AskReddit subreddit.
|
||||
"""
|
||||
|
||||
print_step("Getting subreddit threads...")
|
||||
|
||||
content = {}
|
||||
load_dotenv()
|
||||
reddit = praw.Reddit(client_id=os.getenv("REDDIT_CLIENT_ID"), client_secret=os.getenv("REDDIT_CLIENT_SECRET"),
|
||||
user_agent="Accessing AskReddit threads", username=os.getenv("REDDIT_USERNAME"),
|
||||
password=os.getenv("REDDIT_PASSWORD"), )
|
||||
"""
|
||||
Ask user for subreddit input
|
||||
"""
|
||||
if not os.getenv("SUBREDDIT"):
|
||||
subreddit = reddit.subreddit(
|
||||
input("What subreddit would you like to pull from? ")) # if the env isnt set, ask user
|
||||
else:
|
||||
print_substep(f"Using subreddit: r/{os.getenv('SUBREDDIT')} from environment variable config")
|
||||
subreddit = reddit.subreddit(
|
||||
os.getenv("SUBREDDIT")) # Allows you to specify in .env. Done for automation purposes.
|
||||
|
||||
threads = subreddit.hot(limit=25)
|
||||
submission = list(threads)[random.randrange(0, 25)]
|
||||
os.environ["VIDEO_TITLE"] = str(ascifi(submission.title))
|
||||
print_substep(f"Video will be: {os.getenv('VIDEO_TITLE')} :thumbsup:")
|
||||
try:
|
||||
|
||||
content["thread_url"] = submission.url
|
||||
content["thread_title"] = submission.title
|
||||
content["comments"] = []
|
||||
|
||||
for top_level_comment in submission.comments:
|
||||
content["comments"].append(
|
||||
{"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")
|
||||
return content
|
||||
@@ -0,0 +1,8 @@
|
||||
import os
|
||||
|
||||
|
||||
def cleanup():
|
||||
files = [f for f in os.listdir('.') if f.endswith('.mp4') and 'temp' in f.lower()]
|
||||
for f in files:
|
||||
os.remove(f)
|
||||
|
||||
@@ -1,46 +1,50 @@
|
||||
import random
|
||||
from os import listdir, environ
|
||||
from pathlib import Path
|
||||
from random import randrange
|
||||
from pytube import YouTube
|
||||
from pathlib import Path
|
||||
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
|
||||
from moviepy.editor import VideoFileClip
|
||||
from rich.progress import track
|
||||
|
||||
from utils.console import print_step, print_substep
|
||||
|
||||
|
||||
def get_start_and_end_times(video_length, length_of_clip):
|
||||
|
||||
random_time = randrange(180, int(length_of_clip) - int(video_length))
|
||||
return random_time, random_time + video_length
|
||||
|
||||
|
||||
def download_background():
|
||||
"""Downloads the background video from youtube.
|
||||
"""Downloads the backgrounds/s video from youtube.
|
||||
|
||||
Shoutout to: bbswitzer (https://www.youtube.com/watch?v=n_Dv4JMiwK8)
|
||||
Shoutout to: Orbital Gameplay (https://www.youtube.com/watch?v=2X9QGY__0II)
|
||||
"""
|
||||
Path("assets/backgronds/").mkdir(parents=True, exist_ok=True)
|
||||
background_options = [ # uri , filename , credit
|
||||
("https://www.youtube.com/watch?v=n_Dv4JMiwK8", "parkour.mp4", 'bbswitzer'),
|
||||
# note: make sure the file name doesn't include a - in it
|
||||
("https://www.youtube.com/watch?v=2X9QGY__0II", "rocket_league.mp4", 'Orbital Gameplay'), ]
|
||||
if listdir('assets/backgrounds/') != len(background_options):
|
||||
print_step("We need to download the backgrounds videos. they are fairly large but it's only done once. 😎")
|
||||
print_substep("Downloading the backgrounds video... please be patient 🙏 ")
|
||||
|
||||
if not Path("assets/mp4/background.mp4").is_file():
|
||||
print_step(
|
||||
"We need to download the Minecraft background video. This is fairly large but it's only done once. 😎"
|
||||
)
|
||||
print_substep("Downloading the background video... please be patient 🙏")
|
||||
YouTube("https://www.youtube.com/watch?v=n_Dv4JMiwK8").streams.filter(
|
||||
res="720p"
|
||||
).first().download(
|
||||
"assets/mp4",
|
||||
filename="background.mp4",
|
||||
)
|
||||
print_substep("Background video downloaded successfully! 🎉", style="bold green")
|
||||
for uri, filename, credit in track(background_options, description="Downloading..."):
|
||||
print_step(f"Downloading {filename} from {uri}")
|
||||
YouTube(uri).streams.filter(res="720p").first().download("assets/backgrounds",
|
||||
filename=f"{credit}-{filename}")
|
||||
print_substep("Background videos downloaded successfully! 🎉", style="bold green")
|
||||
|
||||
|
||||
def chop_background_video(video_length):
|
||||
print_step("Finding a spot in the background video to chop...✂️")
|
||||
background = VideoFileClip("assets/mp4/background.mp4")
|
||||
print_step("Finding a spot in the backgrounds video to chop...✂️")
|
||||
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(
|
||||
"assets/mp4/background.mp4",
|
||||
start_time,
|
||||
end_time,
|
||||
targetname="assets/mp4/clip.mp4",
|
||||
)
|
||||
ffmpeg_extract_subclip(f'assets/backgrounds/{choice}', start_time, end_time,
|
||||
targetname="assets/temp/backgrounds.mp4", )
|
||||
print_substep("Background video chopped successfully! 🎉", style="bold green")
|
||||
@@ -1,14 +1,8 @@
|
||||
from moviepy.editor import (
|
||||
VideoFileClip,
|
||||
AudioFileClip,
|
||||
ImageClip,
|
||||
concatenate_videoclips,
|
||||
concatenate_audioclips,
|
||||
CompositeAudioClip,
|
||||
CompositeVideoClip,
|
||||
)
|
||||
from utils.console import print_step
|
||||
import os
|
||||
|
||||
from moviepy.editor import (VideoFileClip, AudioFileClip, ImageClip, concatenate_videoclips, concatenate_audioclips,
|
||||
CompositeAudioClip, CompositeVideoClip)
|
||||
from utils.console import print_step
|
||||
|
||||
W, H = 1080, 1920
|
||||
|
||||
@@ -19,16 +13,13 @@ def make_final_video(number_of_clips):
|
||||
VideoFileClip.reH = lambda clip: clip.resize(width=H)
|
||||
|
||||
background_clip = (
|
||||
VideoFileClip("assets/mp4/clip.mp4")
|
||||
.without_audio()
|
||||
.resize(height=H)
|
||||
.crop(x1=1166.6, y1=0, x2=2246.6, y2=1920)
|
||||
)
|
||||
VideoFileClip("assets/temp/backgrounds.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):
|
||||
audio_clips.append(AudioFileClip(f"assets/mp3/{i}.mp3"))
|
||||
audio_clips.insert(0, AudioFileClip(f"assets/mp3/title.mp3"))
|
||||
audio_clips.append(AudioFileClip(f"assets/temp/mp3/{i}.mp3"))
|
||||
audio_clips.insert(0, AudioFileClip(f"assets/temp/mp3/title.mp3"))
|
||||
audio_concat = concatenate_audioclips(audio_clips)
|
||||
audio_composite = CompositeAudioClip([audio_concat])
|
||||
|
||||
@@ -36,26 +27,23 @@ def make_final_video(number_of_clips):
|
||||
image_clips = []
|
||||
for i in range(0, number_of_clips):
|
||||
image_clips.append(
|
||||
ImageClip(f"assets/png/comment_{i}.png")
|
||||
.set_duration(audio_clips[i + 1].duration)
|
||||
.set_position("center")
|
||||
.resize(width=W - 100),
|
||||
)
|
||||
image_clips.insert(
|
||||
0,
|
||||
ImageClip(f"assets/png/title.png")
|
||||
.set_duration(audio_clips[0].duration)
|
||||
.set_position("center")
|
||||
.resize(width=W - 100),
|
||||
)
|
||||
image_concat = concatenate_videoclips(image_clips).set_position(
|
||||
("center", "center")
|
||||
)
|
||||
ImageClip(f"assets/temp/png/comment_{i}.png").set_duration(audio_clips[i + 1].duration).set_position(
|
||||
"center").resize(width=W - 100), )
|
||||
image_clips.insert(0, ImageClip(f"assets/temp/png/title.png").set_duration(audio_clips[0].duration).set_position(
|
||||
"center").resize(width=W - 100), )
|
||||
image_concat = concatenate_videoclips(image_clips).set_position(("center", "center"))
|
||||
image_concat.audio = audio_composite
|
||||
final = CompositeVideoClip([background_clip, image_concat])
|
||||
final.write_videofile(
|
||||
"assets/final_video.mp4", fps=30, audio_codec="aac", audio_bitrate="192k"
|
||||
)
|
||||
|
||||
for i in range(0, number_of_clips):
|
||||
pass
|
||||
def get_video_title() -> str:
|
||||
title = os.getenv("VIDEO_TITLE") or "final_video"
|
||||
if len(title) <= 35:
|
||||
return title
|
||||
else:
|
||||
return title[0:30] + "..."
|
||||
|
||||
final.write_videofile(f"assets/{get_video_title()}.mp4", fps=30, audio_codec="aac", audio_bitrate="192k")
|
||||
|
||||
|
||||
|
||||
print_step(f"Reddit title: {os.getenv('VIDEO_TITLE')} | Background Credit {os.getenv('background_credit')}")
|
||||
@@ -1,8 +1,10 @@
|
||||
from os import getenv
|
||||
|
||||
from playwright.sync_api import sync_playwright
|
||||
from pathlib import Path
|
||||
from rich.progress import track
|
||||
from utils.console import print_step, print_substep
|
||||
|
||||
from utils.console import print_step, print_substep
|
||||
|
||||
def download_screenshots_of_reddit_posts(reddit_object, screenshot_num):
|
||||
"""Downloads screenshots of reddit posts as they are seen on the web.
|
||||
@@ -14,7 +16,7 @@ def download_screenshots_of_reddit_posts(reddit_object, screenshot_num):
|
||||
print_step("Downloading Screenshots of Reddit Posts 📷")
|
||||
|
||||
# ! Make sure the reddit screenshots folder exists
|
||||
Path("assets/png").mkdir(parents=True, exist_ok=True)
|
||||
Path("assets/temp/png").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with sync_playwright() as p:
|
||||
print_substep("Launching Headless Browser...")
|
||||
@@ -27,17 +29,18 @@ def download_screenshots_of_reddit_posts(reddit_object, screenshot_num):
|
||||
|
||||
if page.locator('[data-testid="content-gate"]').is_visible():
|
||||
# This means the post is NSFW and requires to click the proceed button.
|
||||
if getenv("ALLOW_NSFW").casefold() == "false":
|
||||
print_substep("NSFW Post Detected. Skipping...")
|
||||
from subprocess import call
|
||||
call(["python", "main.py"])
|
||||
exit(1)
|
||||
|
||||
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/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:
|
||||
@@ -47,7 +50,5 @@ 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/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")
|
||||
Whitespace-only changes.
@@ -15,19 +15,19 @@ def save_text_to_mp3(reddit_obj):
|
||||
length = 0
|
||||
|
||||
# Create a folder for the mp3 files.
|
||||
Path("assets/mp3").mkdir(parents=True, exist_ok=True)
|
||||
Path("assets/temp/mp3").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
tts = gTTS(text=reddit_obj["thread_title"], lang="en", slow=False, tld="co.uk")
|
||||
tts.save(f"assets/mp3/title.mp3")
|
||||
length += MP3(f"assets/mp3/title.mp3").info.length
|
||||
tts.save(f"assets/temp/mp3/title.mp3")
|
||||
length += MP3(f"assets/temp/mp3/title.mp3").info.length
|
||||
|
||||
for idx, comment in track(enumerate(reddit_obj["comments"]), "Saving..."):
|
||||
# ! Stop creating mp3 files if the length is greater than 50 seconds. This can be longer, but this is just a good starting point
|
||||
if length > 50:
|
||||
break
|
||||
tts = gTTS(text=comment["comment_body"], lang="en")
|
||||
tts.save(f"assets/mp3/{idx}.mp3")
|
||||
length += MP3(f"assets/mp3/{idx}.mp3").info.length
|
||||
tts.save(f"assets/temp/mp3/{idx}.mp3")
|
||||
length += MP3(f"assets/temp/mp3/{idx}.mp3").info.length
|
||||
|
||||
print_substep("Saved Text to MP3 files Successfully.", style="bold green")
|
||||
# ! Return the index so we know how many screenshots of comments we need to make.
|
||||
|
||||
Reference in new issue
Block a user