From f491479fb7c5efed1c2c9c77689f0800467566d5 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 4 Jun 2022 12:48:35 -0400 Subject: [PATCH] backup --- README.md | 14 ++++++--- main.py | 23 ++++++++++---- reddit/subreddit.py | 11 +++---- utils/cleanup.py | 1 - utils/videos.py | 1 - video_creation/TTSwrapper.py | 5 ++-- video_creation/background.py | 40 ++++++++++++++----------- video_creation/data/videos.json | 16 +++++----- video_creation/screenshot_downloader.py | 11 +++---- video_creation/voices.py | 16 +++++----- 10 files changed, 78 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 82b0004..0f7c5a8 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,16 @@ Created by Lewis Menelaws & [TMRRW](https://tmrrwinc.ca) ## Motivation 🤔 -These videos on TikTok, YouTube and Instagram get MILLIONS of views across all platforms and require very little effort. The only original thing being done is the editing and gathering of all materials... +These videos on TikTok, YouTube and Instagram get MILLIONS of views across all platforms and require very little effort. +The only original thing being done is the editing and gathering of all materials... ... but what if we can automate that process? 🤔 ## Disclaimers 🚨 - This is purely for fun purposes. -- **At the moment**, this repository won't attempt to upload this content through this bot. It will give you a file that you will then have to upload manually. This is for the sake of avoiding any sort of community guideline issues. +- **At the moment**, this repository won't attempt to upload this content through this bot. It will give you a file that + you will then have to upload manually. This is for the sake of avoiding any sort of community guideline issues. ## Requirements @@ -31,17 +33,21 @@ These videos on TikTok, YouTube and Instagram get MILLIONS of views across all p ## Installation 👩‍💻 1. Clone this repository -2. Rename `.env.template` to `.env` and replace all values with the appropriate fields. To get Reddit keys (**required**), visit [the Reddit Apps page.](https://www.reddit.com/prefs/apps) TL;DR set up an app that is a "script". Copy your keys into the `.env` file, along with whether your account uses two-factor authentication. +2. Rename `.env.template` to `.env` and replace all values with the appropriate fields. To get Reddit keys (** + required**), visit [the Reddit Apps page.](https://www.reddit.com/prefs/apps) TL;DR set up an app that is a "script". + Copy your keys into the `.env` file, along with whether your account uses two-factor authentication. 3. Run `pip3 install -r requirements.txt` 4. install [SoX](https://sourceforge.net/projects/sox/files/sox/) 5. Run `playwright install` and `playwright install-deps`. 6. Run `python3 main.py` 7. Enjoy 😎 + ## Contributing & Ways to improve 📈 In its current state, this bot does exactly what it needs to do. However, lots of improvements can be made. -I have tried to simplify the code so anyone can read it and start contributing at any skill level. Don't be shy :) contribute! +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. - [x] Allowing users to choose a reddit thread instead of being randomized. diff --git a/main.py b/main.py index 870ad7e..04e1143 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,17 @@ -from utils.cleanup import cleanup -from utils.console import print_markdown +import os import time + +from dotenv import load_dotenv + from reddit.subreddit import get_subreddit_threads +from utils.cleanup import cleanup +from utils.console import print_markdown 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 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 +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.") @@ -34,9 +39,17 @@ def main(): final_video = make_final_video(number_of_comments) +def run_many(times): + for x in range(times): + main() + + if __name__ == '__main__': try: - main() + if os.getenv('TIMES_TO_RUN'): + run_many(int(os.getenv('TIMES_TO_RUN'))) + else: + main() except KeyboardInterrupt: print_markdown("## Clearing temp files") cleanup() diff --git a/reddit/subreddit.py b/reddit/subreddit.py index cd6bd25..5fc79da 100644 --- a/reddit/subreddit.py +++ b/reddit/subreddit.py @@ -1,11 +1,9 @@ -import re - -from utils.console import print_step, print_substep -import praw import random -from dotenv import load_dotenv from os import getenv, environ +import praw + +from utils.console import print_step, print_substep from utils.videos import check_done TEXT_WHITELIST = set('abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890') @@ -22,7 +20,6 @@ def get_subreddit_threads(): print_step("Getting subreddit threads...") content = {} - load_dotenv() if getenv("REDDIT_2FA").casefold() == "yes": print("\nEnter your two-factor authentication code from your authenticator app.\n") code = input("> ") @@ -66,7 +63,7 @@ def get_subreddit_threads(): 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, }) + "comment_id": top_level_comment.id, }) except AttributeError as e: pass diff --git a/utils/cleanup.py b/utils/cleanup.py index ee3453b..5c31e05 100644 --- a/utils/cleanup.py +++ b/utils/cleanup.py @@ -20,4 +20,3 @@ def cleanup() -> int: os.remove('./assets/temp/mp3/' + file) return count return 0 - diff --git a/utils/videos.py b/utils/videos.py index 4f69b5d..c163076 100644 --- a/utils/videos.py +++ b/utils/videos.py @@ -1,4 +1,3 @@ -import inspect import json from os import getenv diff --git a/video_creation/TTSwrapper.py b/video_creation/TTSwrapper.py index e239e81..4498184 100644 --- a/video_creation/TTSwrapper.py +++ b/video_creation/TTSwrapper.py @@ -1,4 +1,6 @@ -import requests, base64, random, os +import base64 +import random +import requests # https://twitter.com/scanlime/status/1512598559769702406 voices = [ # DISNEY VOICES @@ -74,4 +76,3 @@ class TTTTSWrapper: # TikTok Text-to-Speech Wrapper if ok_or_good == 1: # 1/10 chance of ok voice return random.choice(good_voices['ok']) return random.choice(good_voices['good']) # 9/10 chance of good voice - diff --git a/video_creation/background.py b/video_creation/background.py index f146ade..0a3e1ce 100644 --- a/video_creation/background.py +++ b/video_creation/background.py @@ -1,11 +1,11 @@ import random -from os import listdir, environ +from os import listdir, environ, remove from pathlib import Path from random import randrange -from pytube import YouTube -from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip + from moviepy.editor import VideoFileClip -from rich.progress import Progress +from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip +from yt_dlp import YoutubeDL from utils.console import print_step, print_substep @@ -30,27 +30,31 @@ def download_background(): 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 🙏 ") - with Progress() as progress: - download_task = progress.add_task("[green]Downloading...", total=2) - - for uri, filename, credit in background_options: - print_substep(f"Downloading {filename} from {uri}") - YouTube(uri).streams.filter(res="720p").first().download("assets/backgrounds", - filename=f"{credit}-{filename}") - progress.update(download_task, advance=1) + for uri, filename, credit in background_options: + filename = f"{credit}-{filename}" + ydl_opts = {'outtmpl': f'assets/backgrounds/_raw_{filename}', 'merge_output_format': 'mp4', } + with YoutubeDL(ydl_opts) as ydl: + ydl.download(uri) + videoclip = VideoFileClip(f"assets/backgrounds/{filename}") + new_clip = videoclip.without_audio() + new_clip.write_videofile(f"assets/backgrounds/{filename}") + remove(f'assets/backgrounds/_raw_{filename}') 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...✂️") + print_step("Finding a spot in the background 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(f'assets/backgrounds/{choice}', start_time, end_time, - targetname="assets/temp/backgrounds.mp4", ) - print_substep("Background video chopped successfully! 🎉", style="bold green") + print_substep(choice) + 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") diff --git a/video_creation/data/videos.json b/video_creation/data/videos.json index 2a417ad..0fdcbda 100644 --- a/video_creation/data/videos.json +++ b/video_creation/data/videos.json @@ -1,9 +1,9 @@ [ - { - "id": "v2kd2q", - "time": "1654128204", - "background_credit": "bbswitzer", - "reddit_title": "What movie do you absolutely love yet acknowledge is not a super wellmade movie", - "filename": "What movie do you absolutely l....mp4" - } -] \ No newline at end of file + { + "id": "v2kd2q", + "time": "1654128204", + "background_credit": "bbswitzer", + "reddit_title": "What movie do you absolutely love yet acknowledge is not a super wellmade movie", + "filename": "What movie do you absolutely l....mp4" + } +] diff --git a/video_creation/screenshot_downloader.py b/video_creation/screenshot_downloader.py index 12ea28d..bcc3bb0 100644 --- a/video_creation/screenshot_downloader.py +++ b/video_creation/screenshot_downloader.py @@ -1,12 +1,13 @@ import json from os import getenv - -from playwright.sync_api import sync_playwright from pathlib import Path + +from playwright.sync_api import sync_playwright, ViewportSize from rich.progress import track 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. @@ -31,15 +32,15 @@ def download_screenshots_of_reddit_posts(reddit_object, screenshot_num): context.add_cookies(cookies) # Get the thread screenshot page = context.new_page() + page.set_viewport_size(ViewportSize(width=1920, height=1080)) page.goto(reddit_object["thread_url"]) 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) + from main import main + main() print_substep("Post is NSFW. You are spicy... :fire:") page.locator('[data-testid="content-gate"] button').click() diff --git a/video_creation/voices.py b/video_creation/voices.py index 5f6797b..3815722 100644 --- a/video_creation/voices.py +++ b/video_creation/voices.py @@ -1,13 +1,11 @@ -from os import remove - -import sox from pathlib import Path +import sox from mutagen import MutagenError from mutagen.mp3 import MP3, HeaderNotFoundError -from utils.console import print_step, print_substep from rich.progress import track +from utils.console import print_step, print_substep from video_creation.TTSwrapper import TTTTSWrapper VIDEO_LENGTH: int = 40 # secs @@ -29,11 +27,11 @@ def save_text_to_mp3(reddit_obj): ttttsw.tts(reddit_obj["thread_title"], filename=f"assets/temp/mp3/title.mp3", random_speaker=True) try: length += MP3(f"assets/temp/mp3/title.mp3").info.length - except HeaderNotFoundError: - length = sox.file_info.duration(f"assets/temp/mp3/title.mp3") + except HeaderNotFoundError: # note to self AudioFileClip + length += sox.file_info.duration(f"assets/temp/mp3/title.mp3") com = 0 for comment in track((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_voices starting point + # ! Stop creating mp3 files if the length is greater than VIDEO_LENGTH seconds. This can be longer, but this is just a good_voices starting point if length > VIDEO_LENGTH: break @@ -49,8 +47,8 @@ def save_text_to_mp3(reddit_obj): 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 + # remove(f"assets/temp/mp3/{com}.mp3") + # remove(f"assets/temp/png/comment_{com}.png")# todo might cause odd un-syncing 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.