From eeb5f5504b461afe7adadf5b9d766a2373e0c026 Mon Sep 17 00:00:00 2001 From: Hunter Williams Date: Fri, 1 Dec 2023 00:59:22 -0500 Subject: [PATCH 1/4] Add requirements file --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d8b8810 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +mutagen.mp4 +progress.bar \ No newline at end of file From c72ccee7ac92e572b38f58a01f9433347d0e00a7 Mon Sep 17 00:00:00 2001 From: Hunter Williams Date: Fri, 1 Dec 2023 00:59:42 -0500 Subject: [PATCH 2/4] Auto format and reorder functions --- title-tagging.py | 343 ++++++++++++++++++++++++++++------------------- 1 file changed, 208 insertions(+), 135 deletions(-) diff --git a/title-tagging.py b/title-tagging.py index 5fe351d..618b0e2 100644 --- a/title-tagging.py +++ b/title-tagging.py @@ -4,19 +4,19 @@ import os import sys - # Run the script with '--help' to see more information. class bcolors: - BOLD = '\033[1m' - RED = '\033[91m' - RESET = '\033[0m' - YELLOW = '\033[93m' + BOLD = "\033[1m" + RED = "\033[91m" + RESET = "\033[0m" + YELLOW = "\033[93m" def arguments(): - parser = argparse.ArgumentParser(description=''' + parser = argparse.ArgumentParser( + description=""" A script to embed title tags in video files. Dependencies: Python 3, Mutagen, and Progress @@ -42,137 +42,176 @@ def arguments(): Example 2: File name: 01 - Why Learn Python?.mp4 Extracted title tag: Why Learn Python? - ''', formatter_class=argparse.RawTextHelpFormatter) + """, + formatter_class=argparse.RawTextHelpFormatter, + ) parser.parse_args() -def ask(confirmation_prompt, default_answer_no=False): - while True: - answer = (input(confirmation_prompt).strip()).lower() - if default_answer_no and answer == '' or answer.startswith('n'): - return False - elif answer == '' or answer.startswith('y'): - return True - elif answer == 'exit': - terminate() - else: - print(f'{bcolors.YELLOW}Invalid Input: Please enter yes or no.{bcolors.RESET}') +def example_info(): + return f""" +Correct file name format is as follows +Example 1: +File name: Python 3 Tutorial for Beginners - S01E01 - Why Learn Python?.mp4 +Extracted title tag: Why Learn Python? + +Example 2: +File name: 01 - Why Learn Python?.mp4 +Extracted title tag: Why Learn Python? + +{bcolors.BOLD}Type "exit" at any prompt to exit the script{bcolors.RESET} + +For more information run the script with --help + """ -def capitalize_title(title_string): - ignore = {'a', 'an', 'and', 'as', 'at', 'but', 'by', - 'down', 'for', 'from', 'if', 'in', 'into', - 'like', 'near', 'nor', 'of', 'off', 'on', - 'once', 'onto', 'or', 'over', 'past', 'so', - 'than', 'that', 'the', 'till', 'to', 'upon', - 'v', 'v.', 'vs', 'vs.', 'when', 'with', 'yet'} - title = '' - for word in title_string.split(' '): - if word.lower() in ignore: - if word == title_string.split(' ')[0] or word == title_string.split(' ')[-1]: - if not word.isupper(): - if not word.endswith('s') & (word.replace('s', '')).isupper(): - word = word.capitalize() - else: - word = word.lower() - elif not word.isupper(): - if not word.endswith('s') & (word.replace('s', '')).isupper(): - if not (word.lower()).startswith('ipv'): - word = word.capitalize() - title += str(f'{word} ') - return title + +def terminate(): + print("Exiting script.") + sys.exit() def check_path(directory_path_prompt): search_directory_set = set([]) while True: input_directory = input(directory_path_prompt) - if input_directory.lower() == 'exit': + if input_directory.lower() == "exit": terminate() - if (input_directory.strip()).startswith('.\\'): - input_directory = (input_directory.strip()).replace('.\\', '', 1) + if (input_directory.strip()).startswith(".\\"): + input_directory = (input_directory.strip()).replace(".\\", "", 1) input_directory = os.path.join((os.getcwd()), input_directory) if os.path.isdir(input_directory): search_directory_set.add(input_directory) - if ask('Would you like to add another directory to search (y/N)? ', True): + if ask("Would you like to add another directory to search (y/N)? ", True): continue else: return search_directory_set else: - print(f'{bcolors.YELLOW}Invalid Directory Path: Please enter a valid directory path.{bcolors.RESET}') + print( + f"{bcolors.YELLOW}Invalid Directory Path: Please enter a valid directory path.{bcolors.RESET}" + ) continue -def check_titles(correct_tags_dictionary, merged_tags_dictionary): - if len(correct_tags_dictionary) >= 1: - print(f'{len(correct_tags_dictionary)} file(s) with correct tag(s).') - if len(merged_tags_dictionary) >= 1: - print(f'{bcolors.YELLOW}Found {len(merged_tags_dictionary)} file(s) with incorrect title tag{bcolors.RESET}.') - for file_path, file_title in merged_tags_dictionary.items(): - print(f'{bcolors.YELLOW}Incorrect: Tag for "{file_path}" not successfully set.{bcolors.RESET}') - - -def example_info(): - return f''' -Correct file name format is as follows +def valid_extension(extension_prompt): + valid_extension_list = ["mp4"] + while True: + extension_limit = (input(extension_prompt).strip()).lower() + if extension_limit == "exit": + terminate() + if extension_limit.startswith("."): + extension_limit = extension_limit.replace(".", "", 1) + if extension_limit in valid_extension_list: + return extension_limit + else: + print( + f"{bcolors.YELLOW}Invalid Input: Please enter one of the following supported extensions {valid_extension_list}.{bcolors.RESET}" + ) + continue -Example 1: -File name: Python 3 Tutorial for Beginners - S01E01 - Why Learn Python?.mp4 -Extracted title tag: Why Learn Python? -Example 2: -File name: 01 - Why Learn Python?.mp4 -Extracted title tag: Why Learn Python? +def walk_the_path(valid_directory_set): + path_walked = {} + extension_limit = valid_extension( + "What file extension would you like to use to narrow the search? " + ) + for valid_dir in valid_directory_set: + for root, subdirs, files in os.walk(valid_dir): + for file in files: + if file.endswith(extension_limit): + path_walked[file] = root + if len(path_walked) == 0: + print( + f'{bcolors.YELLOW}No files found when searching for files ending with ".{extension_limit}".{bcolors.RESET}' + ) + terminate() + elif len(path_walked) >= 1: + return path_walked -{bcolors.BOLD}Type "exit" at any prompt to exit the script{bcolors.RESET} -For more information run the script with --help - ''' +def capitalize_title(title_string): + ignore = { + "a", + "an", + "and", + "as", + "at", + "but", + "by", + "down", + "for", + "from", + "if", + "in", + "into", + "like", + "near", + "nor", + "of", + "off", + "on", + "once", + "onto", + "or", + "over", + "past", + "so", + "than", + "that", + "the", + "till", + "to", + "upon", + "v", + "v.", + "vs", + "vs.", + "when", + "with", + "yet", + } + title = "" + for word in title_string.split(" "): + if word.lower() in ignore: + if ( + word == title_string.split(" ")[0] + or word == title_string.split(" ")[-1] + ): + if not word.isupper(): + if not word.endswith("s") & (word.replace("s", "")).isupper(): + word = word.capitalize() + else: + word = word.lower() + elif not word.isupper(): + if not word.endswith("s") & (word.replace("s", "")).isupper(): + if not (word.lower()).startswith("ipv"): + word = word.capitalize() + title += str(f"{word} ") + return title def fetch_titles(path_walked_dictionary): valid_titles = {} for file, root in path_walked_dictionary.items(): - if ' - ' not in file: - print(f'{bcolors.RED}Error: Video File "{os.path.join(root, file)}" is not named correctly.{bcolors.RESET}') - print(f'{bcolors.YELLOW}Run the script with "--help" to see an example of the correct format of a file name.{bcolors.RESET}') + if " - " not in file: + print( + f'{bcolors.RED}Error: Video File "{os.path.join(root, file)}" is not named correctly.{bcolors.RESET}' + ) + print( + f'{bcolors.YELLOW}Run the script with "--help" to see an example of the correct format of a file name.{bcolors.RESET}' + ) else: - title = capitalize_title((((file.split(' - '))[-1])[0:-((len(((file.split('.'))[-1]).strip())+1))].strip())) + title = capitalize_title( + ( + ((file.split(" - "))[-1])[ + 0 : -((len(((file.split("."))[-1]).strip()) + 1)) + ].strip() + ) + ) valid_titles[os.path.join(root, file)] = title.strip() return valid_titles -def handling_tags(merged_tags_dictionary, correct_tags_dictionary): - if len(merged_tags_dictionary) >= 1: - for file_path, file_title in merged_tags_dictionary.items(): - print(f'The title for "{file_path}" would be "{file_title}".') - print(f'Found {len(merged_tags_dictionary)} file(s) with incorrect title tag.') - if len(correct_tags_dictionary) >= 1: - print(f'Found {len(correct_tags_dictionary)} file(s) with correct title tag.') - return True - elif len(merged_tags_dictionary) == 0: - if len(correct_tags_dictionary) >= 1: - print(f'Found {len(correct_tags_dictionary)} file(s) with correct title tag.') - return False - - -def main(): - arguments() - print(example_info()) - search_directory_set = check_path('Which directory would you like to search (recursively)? ') - path_walked = walk_the_path(search_directory_set) - valid_titles = fetch_titles(path_walked) - correct_tags, incorrect_tags, empty_tags, merged_tags = sort_tags(valid_titles) - if handling_tags(merged_tags, correct_tags): - if ask('Would you like to update the file(s) as shown above (Y/n)? '): - update_title_progress(merged_tags) - for dict in [correct_tags, incorrect_tags, empty_tags, merged_tags]: - dict.clear() - correct_tags, incorrect_tags, empty_tags, merged_tags = sort_tags(valid_titles) - check_titles(correct_tags, merged_tags) - terminate() - - def sort_tags(valid_titles_dictionary): correct = {} incorrect = {} @@ -180,8 +219,8 @@ def sort_tags(valid_titles_dictionary): merged = {} for file_path, file_title in valid_titles_dictionary.items(): video_file = mutagen.mp4.MP4(file_path) - if '©nam' in video_file: - if file_title in video_file.get('©nam'): + if "©nam" in video_file: + if file_title in video_file.get("©nam"): correct[file_path] = file_title else: incorrect[file_path] = file_title @@ -192,21 +231,51 @@ def sort_tags(valid_titles_dictionary): return correct, incorrect, empty, merged -def terminate(): - print('Exiting script.') - sys.exit() +def handling_tags(merged_tags_dictionary, correct_tags_dictionary): + if len(merged_tags_dictionary) >= 1: + for file_path, file_title in merged_tags_dictionary.items(): + print(f'The title for "{file_path}" would be "{file_title}".') + print(f"Found {len(merged_tags_dictionary)} file(s) with incorrect title tag.") + if len(correct_tags_dictionary) >= 1: + print( + f"Found {len(correct_tags_dictionary)} file(s) with correct title tag." + ) + return True + elif len(merged_tags_dictionary) == 0: + if len(correct_tags_dictionary) >= 1: + print( + f"Found {len(correct_tags_dictionary)} file(s) with correct title tag." + ) + return False + + +def ask(confirmation_prompt, default_answer_no=False): + while True: + answer = (input(confirmation_prompt).strip()).lower() + if default_answer_no and answer == "" or answer.startswith("n"): + return False + elif answer == "" or answer.startswith("y"): + return True + elif answer == "exit": + terminate() + else: + print( + f"{bcolors.YELLOW}Invalid Input: Please enter yes or no.{bcolors.RESET}" + ) def update_title(tags_dictionary): for file_path, file_title in tags_dictionary.items(): video_file = mutagen.mp4.MP4(file_path) - video_file['©nam'] = [file_title] + video_file["©nam"] = [file_title] video_file.save() def update_title_progress(tags_dictionary): count = len(tags_dictionary) - bar = progress.bar.FillingSquaresBar('Processing', max=count, suffix='%(index)d/%(max)d - %(percent).1f%%') + bar = progress.bar.FillingSquaresBar( + "Processing", max=count, suffix="%(index)d/%(max)d - %(percent).1f%%" + ) for tag in range(count): update_title(tags_dictionary) count -= 1 @@ -214,35 +283,39 @@ def update_title_progress(tags_dictionary): bar.finish() -def valid_extension(extension_prompt): - valid_extension_list = ['mp4'] - while True: - extension_limit = (input(extension_prompt).strip()).lower() - if extension_limit == 'exit': - terminate() - if extension_limit.startswith('.'): - extension_limit = extension_limit.replace('.', '', 1) - if extension_limit in valid_extension_list: - return extension_limit - else: - print(f'{bcolors.YELLOW}Invalid Input: Please enter one of the following supported extensions {valid_extension_list}.{bcolors.RESET}') - continue +def check_titles(correct_tags_dictionary, merged_tags_dictionary): + if len(correct_tags_dictionary) >= 1: + print(f"{len(correct_tags_dictionary)} file(s) with correct tag(s).") + if len(merged_tags_dictionary) >= 1: + print( + f"{bcolors.YELLOW}Found {len(merged_tags_dictionary)} file(s) with incorrect title tag{bcolors.RESET}." + ) + for file_path, file_title in merged_tags_dictionary.items(): + print( + f'{bcolors.YELLOW}Incorrect: Tag for "{file_path}" not successfully set.{bcolors.RESET}' + ) -def walk_the_path(valid_directory_set): - path_walked = {} - extension_limit = valid_extension('What file extension would you like to use to narrow the search? ') - for valid_dir in valid_directory_set: - for root, subdirs, files in os.walk(valid_dir): - for file in files: - if file.endswith(extension_limit): - path_walked[file] = root - if len(path_walked) == 0: - print(f'{bcolors.YELLOW}No files found when searching for files ending with ".{extension_limit}".{bcolors.RESET}') - terminate() - elif len(path_walked) >= 1: - return path_walked +def main(): + arguments() + print(example_info()) + search_directory_set = check_path( + "Which directory would you like to search (recursively)? " + ) + path_walked = walk_the_path(search_directory_set) + valid_titles = fetch_titles(path_walked) + correct_tags, incorrect_tags, empty_tags, merged_tags = sort_tags(valid_titles) + if handling_tags(merged_tags, correct_tags): + if ask("Would you like to update the file(s) as shown above (Y/n)? "): + update_title_progress(merged_tags) + for dict in [correct_tags, incorrect_tags, empty_tags, merged_tags]: + dict.clear() + correct_tags, incorrect_tags, empty_tags, merged_tags = sort_tags( + valid_titles + ) + check_titles(correct_tags, merged_tags) + terminate() -if __name__ == '__main__': +if __name__ == "__main__": main() From 99b6b5d9f9e13375218fab0f1d0f8fd15caabc24 Mon Sep 17 00:00:00 2001 From: Hunter Williams Date: Fri, 1 Dec 2023 17:27:17 -0500 Subject: [PATCH 3/4] Simplify titlization --- title-tagging.py | 81 +++++------------------------------------------- 1 file changed, 8 insertions(+), 73 deletions(-) diff --git a/title-tagging.py b/title-tagging.py index 618b0e2..91acbd3 100644 --- a/title-tagging.py +++ b/title-tagging.py @@ -129,86 +129,22 @@ def walk_the_path(valid_directory_set): return path_walked -def capitalize_title(title_string): - ignore = { - "a", - "an", - "and", - "as", - "at", - "but", - "by", - "down", - "for", - "from", - "if", - "in", - "into", - "like", - "near", - "nor", - "of", - "off", - "on", - "once", - "onto", - "or", - "over", - "past", - "so", - "than", - "that", - "the", - "till", - "to", - "upon", - "v", - "v.", - "vs", - "vs.", - "when", - "with", - "yet", - } - title = "" - for word in title_string.split(" "): - if word.lower() in ignore: - if ( - word == title_string.split(" ")[0] - or word == title_string.split(" ")[-1] - ): - if not word.isupper(): - if not word.endswith("s") & (word.replace("s", "")).isupper(): - word = word.capitalize() - else: - word = word.lower() - elif not word.isupper(): - if not word.endswith("s") & (word.replace("s", "")).isupper(): - if not (word.lower()).startswith("ipv"): - word = word.capitalize() - title += str(f"{word} ") - return title - - def fetch_titles(path_walked_dictionary): valid_titles = {} - for file, root in path_walked_dictionary.items(): - if " - " not in file: + for file_name, root in path_walked_dictionary.items(): + if " - " not in file_name: print( - f'{bcolors.RED}Error: Video File "{os.path.join(root, file)}" is not named correctly.{bcolors.RESET}' + f'{bcolors.RED}Error: Video file "{os.path.join(root, file_name)}" is not named correctly.{bcolors.RESET}' ) print( f'{bcolors.YELLOW}Run the script with "--help" to see an example of the correct format of a file name.{bcolors.RESET}' ) else: - title = capitalize_title( - ( - ((file.split(" - "))[-1])[ - 0 : -((len(((file.split("."))[-1]).strip()) + 1)) - ].strip() - ) + file_extension = os.path.splitext(file_name)[-1] + file_title = ( + file_name.removesuffix(file_extension).split("-")[-1].strip().title() ) - valid_titles[os.path.join(root, file)] = title.strip() + valid_titles[os.path.join(root, file_name)] = file_title return valid_titles @@ -302,8 +238,7 @@ def main(): search_directory_set = check_path( "Which directory would you like to search (recursively)? " ) - path_walked = walk_the_path(search_directory_set) - valid_titles = fetch_titles(path_walked) + valid_titles = fetch_titles(walk_the_path(search_directory_set)) correct_tags, incorrect_tags, empty_tags, merged_tags = sort_tags(valid_titles) if handling_tags(merged_tags, correct_tags): if ask("Would you like to update the file(s) as shown above (Y/n)? "): From 804b67bf51287fcc66f26624a72fff6c77423091 Mon Sep 17 00:00:00 2001 From: Hunter Williams Date: Fri, 1 Dec 2023 17:29:33 -0500 Subject: [PATCH 4/4] Cleanup --- title-tagging.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/title-tagging.py b/title-tagging.py index 91acbd3..361707a 100644 --- a/title-tagging.py +++ b/title-tagging.py @@ -141,10 +141,9 @@ def fetch_titles(path_walked_dictionary): ) else: file_extension = os.path.splitext(file_name)[-1] - file_title = ( + valid_titles[os.path.join(root, file_name)] = ( file_name.removesuffix(file_extension).split("-")[-1].strip().title() ) - valid_titles[os.path.join(root, file_name)] = file_title return valid_titles