Merge remote-tracking branch 'origin/master'

# Conflicts:
#	.env.template
#	reddit/subreddit.py
#	video_creation/TTSwrapper.py
#	video_creation/background.py
pull/418/head
Jason 3 years ago
commit 25c198dff3

@ -24,11 +24,6 @@ def main():
def get_obj():
reddit_obj = get_subreddit_threads()
for comment in (reddit_obj["comments"]):
if len(comment) > 250:
print(comment)
reddit_obj["comments"].remove(comment)
print(reddit_obj["comments"])
return reddit_obj
reddit_object = get_obj()
@ -36,7 +31,7 @@ def main():
download_screenshots_of_reddit_posts(reddit_object, number_of_comments)
download_background()
chop_background_video(length)
final_video = make_final_video(number_of_comments)
final_video = make_final_video(number_of_comments, length)
def run_many(times):

@ -1,24 +1,26 @@
import random
from os import getenv, environ
import re
from utils.console import print_step, print_substep
import praw
import random
from dotenv import load_dotenv
from os import getenv, environ
from utils.console import print_step, print_substep
from utils.videos import check_done
TEXT_WHITELIST = set('abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890')
def textify(text):
return ''.join(filter(TEXT_WHITELIST.__contains__, text))
def get_subreddit_threads():
"""
Returns a list of threads from the AskReddit subreddit.
"""
print_step("Getting subreddit threads...")
content = {}
if getenv("REDDIT_2FA").casefold() == "yes":
print("\nEnter your two-factor authentication code from your authenticator app.\n")
@ -29,29 +31,32 @@ def get_subreddit_threads():
else:
passkey = getenv("REDDIT_PASSWORD")
reddit = praw.Reddit(client_id=getenv("REDDIT_CLIENT_ID"), client_secret=getenv("REDDIT_CLIENT_SECRET"),
user_agent="Accessing AskReddit threads", username=getenv("REDDIT_USERNAME"),
user_agent="Accessing Reddit threads", username=getenv("REDDIT_USERNAME"),
passkey=passkey, )
"""
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
else:
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.
if getenv('POST_ID'):
submission = reddit.submission(id=getenv('POST_ID'))
else:
if getenv("SUBREDDIT"): # Allows you to specify in .env. Done for automation purposes.
subreddit = reddit.subreddit(getenv("SUBREDDIT"))
else:
# Prompt the user to enter a subreddit
try:
subreddit = reddit.subreddit(input("What subreddit would you like to pull from? "))
except ValueError:
subreddit = reddit.subreddit("askreddit")
print_substep("Subreddit not defined. Using AskReddit.")
threads = subreddit.hot(limit=25)
submission = list(threads)[random.randrange(0, 25)]
submission = check_done(submission)
if submission == None:
return get_subreddit_threads() # todo check
print_substep(f"Video will be: {submission.title} :thumbsup:")
print_substep(
f'subreddit thread is: {submission.title}\n(if you dont like this, you can change it by exiting and rerunning the program)')
environ["VIDEO_TITLE"] = str(textify(submission.title)) # todo use global instend of env vars
environ["VIDEO_ID"] = str(textify(submission.id))
try:
@ -61,11 +66,11 @@ def get_subreddit_threads():
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, })
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, })
except AttributeError as e:
pass
print_substep("Received subreddit thread Successfully.", style="bold green")
print_substep("Received subreddit threads Successfully.", style="bold green")
return content

@ -16,6 +16,5 @@ def check_done(redditobj): # don't set this to be run anyplace that isn't subre
'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')
from reddit.subreddit import get_subreddit_threads
return get_subreddit_threads() # recursive func
return None
return redditobj

@ -1,6 +1,6 @@
import base64
import random
import requests
import requests, base64, random, os
import re
from moviepy.editor import AudioFileClip, concatenate_audioclips, CompositeAudioClip
# https://twitter.com/scanlime/status/1512598559769702406
voices = [ # DISNEY VOICES
@ -56,19 +56,30 @@ class TTTTSWrapper: # TikTok Text-to-Speech Wrapper
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):
if len(req_text) > 299:
return ValueError("Text too long must be under 299 characters")
if random_speaker:
req_text = req_text.replace("+", "plus").replace(" ", "+").replace("&", "and")
req_text = req_text.replace("+", "plus").replace(" ", "+").replace("&", "and")
voice = self.randomvoice() if random_speaker else 'en_us_002'
r = requests.post(f"{self.URI_BASE}{voice}&req_text={req_text}&speaker_map_type=0")
vstr = [r.json()["data"]["v_str"]][0]
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")
vstr = [r.json()["data"]["v_str"]][0]
b64d = base64.b64decode(vstr)
b64d = base64.b64decode(vstr)
with open(f"{filename}-{chunkId}", "wb") as out:
out.write(b64d)
with open(filename, "wb") as out:
out.write(b64d)
audio_clips.append(AudioFileClip(f"{filename}-{chunkId}"))
chunkId = chunkId+1;
audio_concat = concatenate_audioclips(audio_clips)
audio_composite = CompositeAudioClip([audio_concat])
audio_composite.write_audiofile(filename, 44100, 2, 2000, None)
@staticmethod
def randomvoice():
@ -76,3 +87,4 @@ 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

@ -1,11 +1,11 @@
import random
from os import listdir, environ, remove
from os import listdir, environ
from pathlib import Path
from random import randrange
from moviepy.editor import VideoFileClip
from pytube import YouTube
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
from yt_dlp import YoutubeDL
from moviepy.editor import VideoFileClip
from rich.progress import Progress
from utils.console import print_step, print_substep
@ -30,31 +30,27 @@ 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:
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}')
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="1080p").first().download("assets/backgrounds",
filename=f"{credit}-{filename}")
progress.update(download_task, advance=1) # todo remove
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...")
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)
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")
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")

@ -4,5 +4,11 @@
"value": "eyJwcmVmcyI6eyJ0b3BDb250ZW50RGlzbWlzc2FsVGltZSI6MCwiZ2xvYmFsVGhlbWUiOiJSRURESVQiLCJuaWdodG1vZGUiOnRydWUsImNvbGxhcHNlZFRyYXlTZWN0aW9ucyI6eyJmYXZvcml0ZXMiOmZhbHNlLCJtdWx0aXMiOmZhbHNlLCJtb2RlcmF0aW5nIjpmYWxzZSwic3Vic2NyaXB0aW9ucyI6ZmFsc2UsInByb2ZpbGVzIjpmYWxzZX0sInRvcENvbnRlbnRUaW1lc0Rpc21pc3NlZCI6MH19",
"domain": ".reddit.com",
"path": "/"
},
{
"name": "eu_cookie",
"value": "{%22opted%22:true%2C%22nonessential%22:false}",
"domain": ".reddit.com",
"path": "/"
}
]

@ -0,0 +1,8 @@
[
{
"name": "eu_cookie",
"value": "{%22opted%22:true%2C%22nonessential%22:false}",
"domain": ".reddit.com",
"path": "/"
}
]

@ -3,8 +3,8 @@ 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 import io
from utils.cleanup import cleanup
from utils.console import print_step, print_substep
@ -12,7 +12,7 @@ from utils.console import print_step, print_substep
W, H = 1080, 1920
def make_final_video(number_of_clips):
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)
@ -65,7 +65,11 @@ def make_final_video(number_of_clips):
if not exists('./results'):
print_substep('the results folder didn\'t exist so I made it')
os.mkdir("./results")
final.write_videofile(f"results/{filename}", fps=30, audio_codec="aac", audio_bitrate="192k")
final.write_videofile("temp.mp4", fps=30, audio_codec="aac", audio_bitrate="192k")
io.ffmpeg_tools.ffmpeg_extract_subclip("temp.mp4", 0, length, targetname=f"results/{filename}")
os.remove("temp.mp4")
print_step("Removing temporary files 🗑")
cleanups = cleanup()
print_substep(f"Removed {cleanups} temporary files 🗑")

@ -27,9 +27,11 @@ 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.json')
cookies = json.load(cookie_file)
context.add_cookies(cookies)
cookie_file = open('./video_creation/data/cookie-dark-mode.json')
else:
cookie_file = open('./video_creation/data/cookie-light-mode.json')
cookies = json.load(cookie_file)
context.add_cookies(cookies)
# Get the thread screenshot
page = context.new_page()
page.set_viewport_size(ViewportSize(width=1920, height=1080))

Loading…
Cancel
Save