def youtube_detector(timestamp): # Downloading all the YouTube Sources for vid in ytSources: prettyPrint( bcolors.ENDC, os.popen("youtube-dl -o \"{}\" -f mp4 {}".format( fullPath("data/rawVideos/%(id)s.mp4"), fullPath(vid))).read()) # Editing each of the videos for targetVid in os.listdir("data/rawVideos"): cut_video(targetVid)
def cut_video(video_path): scenes = find_scenes("data/rawVideos/{}".format(video_path)) prettyPrint( bcolors.OKBLUE, "{0} number of scenes detected: {1}".format(video_path, len(scenes))) # Finally splits the video into clips split_video( video_path, scenes, "data/rawClips/{}\\Scene.mkv".format(video_path), video_path, suppress_output=False, )
def newUpload(): with open(fullPath("data/auth.json")) as jsonfile: auth = json.load(jsonfile) opts = webdriver.ChromeOptions() opts.binary_location = "/usr/bin/google-chrome" opts.accept_untrusted_certs = True opts.assume_untrusted_cert_issuer = True for arg in arguments: opts.add_argument(arg) driver = webdriver.Chrome(executable_path="data/browser/chromedriver", options=opts) # Authenticate into Youtube Studio driver.get( "https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&prompt=consent&response_type=code&client_id=407408718192.apps.googleusercontent.com&scope=email&access_type=offline&flowName=GeneralOAuthFlow" ) # Get to upload screen CREATE = driver.find_element_by_id("create-icon").click() UPLOAD = driver.find_element_by_id("text-item-0").click() content = os.listdir(fullPath("data/output"))[0] selectFiles = driver.find_element_by_id("select-files-button").click() selectFiles.send_keys(content) # Publish video to youtube title = "{} memes for {}".format(random.choice(titles), names.get_first_name()) titleBox = driver.find_element_by_id("textbox").send_keys(title) nextButon = driver.find_element_by_id("next-button") nextButon.click() nextButon.click() # Finally uploads the video doneButton = driver.find_element_by_id("done-button").click() driver.close() prettyPrint(bcolors.OKGREEN, "Video finished uploading, closing connection")
def VideoFormatter(target): targetPath = fullPath("data/rawClips/{}.mp4".format(target)) outputPath = fullPath("data/sync_data/{}.mp4".format(target)) prettyPrint(bcolors.OKBLUE, "Formatting data/rawClips/{}.mp4".format(target)) # This is a really long command so here are a bunch of comments explaining it # Step #1: FFMPEG makes two copies, [original] and [copy] # Step #2: Take [copy] and scale it to 16/9 so all videos are the same size, and apply a blur effect to it # Step #3: Append [original] on top of [copy] and output the finished video to data/sync_data prettyPrint( bcolors.ENDC, os.popen( "ffmpeg -i {} -vf 'split[original][copy];[copy]scale=ih*16/9:-1,crop=h=iw*9/16,gblur=sigma=20[blurred];[blurred][original]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2' -video_track_timescale 29971 -ac 1 {}" .format(targetPath, outputPath)).read()) # Checks to make sure the video are valid files try: float( os.popen( "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 {}" .format(outputPath)).read()) except Exception as e: prettyPrint( bcolors.WARNING, "Non-viable file, file will be removed. Error code {}".format(e)) os.remove(outputPath) # Cleans up the files and exist the thread os.remove(targetPath) sys.exit("Exiting the thread")
def split_video(input_video_paths, scene_list, output_file_template, video_name, suppress_output=False): if not input_video_paths or not scene_list: return logging.info( 'Splitting input video%s using mkvmerge, output path template:\n %s', 's' if len(input_video_paths) > 1 else '', output_file_template) ret_val = None # mkvmerge automatically appends '-$SCENE_NUMBER'. output_file_name = output_file_template.replace('-${SCENE_NUMBER}', '') output_file_name = output_file_template.replace('-$SCENE_NUMBER', '') output_file_template = Template(output_file_name) output_file_name = output_file_template.safe_substitute( VIDEO_NAME=video_name, SCENE_NUMBER='') # Actually make the system call to MKVMerge try: call_list = ['mkvmerge'] call_list += [ '-o', output_file_name, '--split', 'parts:%s' % ','.join([ '%s-%s' % (start_time.get_timecode(), end_time.get_timecode()) for start_time, end_time in scene_list ]), "data/rawVideos/{}".format(input_video_paths) ] total_frames = scene_list[-1][1].get_frames( ) - scene_list[0][0].get_frames() processing_start_time = time.time() ret_val = invoke_command(call_list) print('') prettyPrint( bcolors.OKBLUE, ('Average processing speed %.2f frames/sec.', float(total_frames) / (time.time() - processing_start_time))) # Basically just some error handling except CommandTooLong: prettyPrint(bcolors.WARNING, "COMMAND_TOO_LONG_STRING: {}".format(call_list)) except OSError: prettyPrint( bcolors.WARNING, 'mkvmerge could not be found on the system.' ' Please install mkvmerge to enable video output support.') if ret_val is not None and ret_val != 0: prettyPrint(bcolors.WARNING, ('Error splitting video (mkvmerge returned %d).', ret_val))
def reddit_detector(timestamp, source): # Gets the creds from disk with open(fullPath("data/auth.json")) as jsonfile: auth = json.load(jsonfile) # Configures PRAW creds prettyPrint(bcolors.OKBLUE, "Authenticating provided credentials") redditAuth = praw.Reddit(client_id=auth['reddit']['client_id'], client_secret=auth['reddit']['client_secret'], user_agent=auth['reddit']['user_agent'], username=auth['reddit']['username'], password=auth['reddit']['password']) prettyPrint(bcolors.OKBLUE, "Checking and downloading content from {}".format(source)) # Generates a list of moderators, this allows us to filter out their posts mods = [] for moderator in redditAuth.subreddit(source).moderator(): mods.append(str(moderator)) # Downloads all of the videos for targetSubmission in redditAuth.subreddit(source).hot(): if not (os.path.exists( fullPath("data/rawClips/{}.mp4".format( targetSubmission.id)))) and not (os.path.exists( fullPath("data/rawClips/{}.mp4".format( targetSubmission.id)))): if not (str(targetSubmission.author) in mods): prettyPrint( bcolors.OKBLUE, "Thread {} is now downloading {} from {} on Reddit.". format(threading.currentThread().ident, targetSubmission.id, source)) prettyPrint( bcolors.ENDC, os.popen("youtube-dl --no-continue -o \"{}\" {}".format( fullPath("data/rawClips/{}.mp4".format( targetSubmission.id)), targetSubmission.url)).read()) fT = threading.Thread(target=VideoFormatter, args=(targetSubmission.id, )) fT.start()
def detectorDirector(): # Reddit Detector startTime = time.perf_counter() prettyPrint(bcolors.OKBLUE, "Checking reddit sources and downloading any new content") redditThreads = [] for source in redditSources: t = threading.Thread(target=reddit_detector, args=(datetime.utcnow(), source)) redditThreads.append(t) t.start() prettyPrint(bcolors.OKBLUE, "All threads finished, closing all active processes") for threads in redditThreads: threads.join() # A little alert to let the user know the function is over and how long it took endTime = time.perf_counter() prettyPrint( bcolors.OKGREEN, f"Reddit sources checked and new content downloaded. Process took {endTime - startTime:0.4f} seconds" )
def GenerateVideo(): # Gets minimum length of video (between 11 and 14 minutes) videoLength = random.randint(660, 841) prettyPrint( bcolors.OKBLUE, "Expected video length is {}".format( datetime.timedelta(seconds=videoLength))) # A list of which clips to use and how long the video is currently clipPaths = [] totalLength = 0 # Randomly selecting clips to add until the video is long enough while (totalLength < videoLength): newChoice = fullPath("data/sync_data/{}".format( random.choice(os.listdir(fullPath("data/sync_data"))))) if newChoice not in clipPaths: try: totalLength += float( os.popen( "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 {}" .format(newChoice)).read()) clipPaths.append(newChoice) except Exception as e: prettyPrint( bcolors.WARNING, "Exception thrown, continuing with process. Exception: {}". format(e)) # Just some output for the user prettyPrint( bcolors.OKBLUE, "Actual video length is {} and contains {} videos. All file paths are listed below" .format(datetime.timedelta(seconds=int(totalLength)), len(clipPaths))) # Logs the video files for future reference logString = "" spacing = len(str(datetime.datetime.now())) + 4 for path in clipPaths: logString += "{} || ".format(path) logString += "\n" for x in range(spacing): logString += " " prettyPrint(bcolors.ENDC, logString) # Edits the video together startTime = time.perf_counter() # Creates a list of the input files for FFMPEG with open(fullPath("inputPaths.txt"), "a") as inputPathFile: ouputString = "" for inputPath in clipPaths: ouputString += "file '{}' \n".format(inputPath) inputPathFile.write(ouputString) # Finally edits the clips togeather vidIndex = len(os.listdir(fullPath("/data/output"))) + 1 prettyPrint( bcolors.ENDC, os.popen("ffmpeg -f concat -safe 0 -i {} -c copy {}".format( fullPath("inputPaths.txt"), fullPath("data/output/video_{}.mp4".format(vidIndex)))).read()) os.remove(fullPath("inputPaths.txt")) # A little alert to let the user know the function is over and how long it took endTime = time.perf_counter() prettyPrint( bcolors.OKGREEN, f"Collected clips and edited video. Process took {endTime - startTime:0.4f} seconds" )